1. 程式人生 > >黑馬程式設計師__JAVA基礎__集合(一)

黑馬程式設計師__JAVA基礎__集合(一)

------------android培訓java培訓、java學習型技術部落格、期待與您交流! ------------

1.概述

    面嚮物件語言對事物的體現都是以物件的形式,所以為了方便對多個物件的操作,就對物件進行儲存,集合就是儲存物件最常用的一種方式。

    java語言的java.util包中提供了一些集合類,這些集合又被成為容器,提到容器不難會想象到陣列,集合類與陣列的不同之處。

陣列與集合不同之處:

    陣列長度是固定的,集合長度是可變的

    陣列中可以儲存基本資料型別,集合只能儲存物件。

集合的特點:

    集合只用於儲存物件,集合長度是可變的,集合可以儲存不同型別的物件

集合有List集合,Set集合,Map集合,其中List和Set集合實現了Collection介面,各個介面還提供了不同的實現類。

集合的框架構成及分類:


2.Collection介面

Collection介面的有兩個子介面:List和Set,List元素有序,元素可以重複,Set元素無序,元素要求唯一。

Collection

|---->List可存放重複元素,元素存取是有序的。因為該集合體繫有索引。

    |---->Vector:底層的資料結構是陣列,執行緒安全,但速度慢,已被ArrayList替代。

    |---->ArrayList:底層的資料結構是陣列。特點:查詢速度很快。但是增刪稍慢。執行緒不同步。

    |---->LinkedList:底層使用的連結串列資料結構。特點:增刪速度很快,查詢稍慢。執行緒不同步。

|---->Set元素是無序(存入和取出的順序不一定一致),元素不可以重複

    |---->HashSet:底層資料結構是雜湊表,是執行緒不安全的,不同步。

    |---->TreeSet:可以對Set集合中的元素進行排序

Collection介面的功能:

    1.新增

    boolean add(Object obj):新增單個元素

    boolean addAll(Collection c):新增多個元素

2.刪除

    void clear():移除所有元素

    boolean remove(Object o):移除單個元素,有一個刪除,就返回true

    boolean removeAll(Collection c):移除多個元素

3.判斷

    boolean contains(Object obj):判斷元素是否存在

    boolean containsAll(Collection c):判斷一個集合的元素是否包含在當前集合中

    boolean isEmpty():判斷集合是否為空

4.獲取

    Iterator iterator():返回集合上的一個迭代器

    int size():元素個數

5.獲取交集

    boolean retainAll(Collection c):交集

6.集合變陣列

    Object[] toArray()

迭代器Iterator

    迭代器是取出集合中元素的一種方式,會直接訪問集合中的元素。

    所以將迭代器通過內部類的形式來進行描述。

    通過容器的iterator()方法獲取該內部類的物件。

迭代器的方法:

    boolean hasNext()判斷是否還有元素可以迭代

    next()返回迭代的下一個元素,獲取的元素預設為Object類

    注意:

    1.迭代器在Collcection介面中是通用的,它替代了Vector類中的Enumeration(列舉)

    2.迭代器的next()方法是自動向下取元素,要避免出現NoSuchElementException

    3.迭代器的next方法返回值型別是Object,所以要記得型別轉換

3.List

    可存放重複元素,元素存取是有序的。因為該集合體繫有索引。

List介面功能:

    1.新增元素

    void add(int index, Object element):在指定位置新增指定元素

    boolean addAll(index i,Collection<? extends E> c)

    2.刪除元素

    Object remove(int index):返回並刪除指定位置的元素

    3.修改元素

    Object set(int index, Object element):修改指定位置的元素

    4.查詢元素

    Object get(int index):根據指定索引獲取元素

    List<E> subList(int fromIndex, int toIndex)返回列表中指定的 fromIndex(包括)和toIndex(不包括)之間的部分檢視。

    int indexOf(Object o)返回此列表中第一次出現的指定元素的索引,如不包括,返回-1

    ListIterator listIterator()List特有的迭代器

List特有迭代器

    ListIterator<E> listIterator():返回按適當順序在列表的元素上進行迭代的迭代器。

    在迭代時,不可以通過集合物件的方法操作集合中的元素,因為會發生ConcurrentModificationException異常。

    注:ConcurrentModificationException異常是指當方法檢測到物件的併發修改,但不允許這種修改時,丟擲此異常,這個地方是指在用迭代器的方法操作集合的時候,又用集合本身的方法來操作這個集合,所以丟擲這個異常

    在迭代器時,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能對元素進行判斷,取出,刪除的操作,如果想要其他的操作如新增,修改等,就需要使用其子介面,ListIterator

    該介面只能通過List集合的listIterator方法獲取。例:ListIterator it = List集合名. listIterator();

List迭代器特有方法:

    void add(E e) 將指定的元素插入列表(可選操作)。

    boolean hasPrevious()  如果以逆向遍歷列表,列表迭代器有多個元素,則返回 true。 

    int nextIndex() 返回對 next 的後續呼叫所返回元素的索引。         

    E previous() 返回列表中的前一個元素。    

    int previousIndex() 返回對 previous 的後續呼叫所返回元素的索引。    

    void set(E e) 用指定元素替換 next 或 previous 返回的最後一個元素(可選操作)。

    void remove()從列表中移除由 next 或 previous 返回的最後一個元素(可選操作)。

List實現類

Vector

    底層的資料結構是陣列,查詢快,增刪慢,執行緒同步,效率低已被ArrayList替代

Vector特有方法:

    1.新增元素

    void addElement(Object obj) JDK1.2 後改為了add(Object obj)

    2.獲取元素

    Object elementAt(int index) JDK1.2後就改為了get(int index),通過角標拿元素

    3.遍歷元素

    Enumeration elements() JDK1.2後就改為Iterator iterator()

    boolean hasMoreElements() JDK1.2後就改為boolean hasNext()

    Object nextElement() JDK1.2後就改為了 Object next()

    Enumeration elements() 

    Enumeration就是列舉,列舉就是Vector特有的取出方式。此介面的功能與 Iterator 介面的功能是重複的,Iterator介面添加了一個可選的移除操作,並使用較短的方法名。新的實現應該優先考慮使用Iterator介面而不是Enumeration介面。

Vector取出元素示例程式碼:

class VectorDemo 
{
	public static void main(String[] args) 
	{
		Vector v = new Vector();

		v.add("java01");//新增元素
		v.add("java02");
		v.add("java03");
		v.add("java04");

		Enumeration en = v.elements();//列舉的方式取出元素
		while(en.hasMoreElements())
		{
			System.out.println(en.nextElement());
		}
	}
}

Arraylist

底層的資料結構使用的是陣列結構。特點:查詢速度很快。但是增刪稍慢。執行緒不同步

    練習:去除ArrayList集合中的重複元素

    思路:新建立一個集合,遍歷原集合往新集合裡面存,在存之前進行是否有這個元素的判斷。

import java.util.*;
class ArrayListTest 
{

	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();

		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java03");
		
		al =  singleElemen(al);
		sop(al);
	}

	public static ArrayList singleElement(ArrayList al)
	{
		//定義一個臨時容器。
		ArrayList newAl = new ArrayList();
		Iterator it = al.iterator();//使用迭代器
		while(it.hasNext())
		{
			Object obj = it.next();
			if(!newAl.contains(obj))//判斷是否有遍歷到元素
				newAl.add(obj);
		}
		return newAl;
	}
}

LinkList

底層使用的連結串列資料結構。特點:增刪速度很快,查詢稍慢,執行緒不同步。

LinkList特有方法:

    1.新增元素:

    void addFirst(E e) 將指定元素插入此列表的開頭。 

    void addLast(E e) 將指定元素新增到此列表的結尾。 

    2.獲取元素:

    E getFirst()返回此列表的第一個元素。 

    E getLast()返回此列表的最後一個元素。 

    3.刪除元素:

    E removeFirst()移除並返回此列表的第一個元素。  

    E removeLast()移除並返回此列表的最後一個元素。 

測試程式碼示例:

class LinkedListDemo
{
	public static void main(String[] args)
	{
		LinkedList link = new LinkedList();//建立物件
		link.add("hello");//新增元素
		link.add("world");
		//特有方法:新增在列表開頭與末尾
		link.addFirst("start");
		link.addLast("over");

		// 獲取元素
		System.out.println("getFirst:" + link.getFirst());
		System.out.println("getLast:" + link.getLast());
		// 遍歷
		Iterator it = link.iterator();
		while (it.hasNext())
		{
			String s = (String) it.next();
			System.out.println(s);
		}
	}
}

4.Set集合

    Set接口裡面存放的是元素是無序唯一的,可以包含null。Set集合是無序的,因此只能用迭代器獲取元素。Set的子類包括HashSet和TreeSet

    Set集合的功能和Collection是一致的.

HashSet:

底層資料結構是雜湊表。是執行緒不安全的。不同步。

HashSet是如何保證元素唯一性的呢?

    是通過元素的兩個方法,hashCode和equals來完成。

    如果元素的HashCode值相同,才會判斷equals是否為true。

    如果元素的hashcode值不同,不會呼叫equals。

注意:對於判斷元素是否存在,以及刪除等操作,依賴的方法是元素的hashcode和equals方法

練習:往hashSet集合中存入自定物件,姓名和年齡相同為同一個人,重複元素。複寫hashCode和equals方法

import java.util.*;

class HashSetTest 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		HashSet hs = new HashSet();

		hs.add(new Person("a1",11));
		hs.add(new Person("a2",12));
		hs.add(new Person("a3",13));
		hs.add(new Person("a2",12));//新增複雜元素,會呼叫比較器不將此元素新增至列表
		hs.add(new Person("a4",14));

		Iterator it = hs.iterator();

		while(it.hasNext())
		{
			Person p = (Person)it.next();
			sop(p.getName()+"::"+p.getAge());
		}
	}
}

class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public int hashCode()//複寫hashCode方法
	{
		System.out.println(this.name+"....hashCode");
		return name.hashCode()+age*37;
	}

	public boolean equals(Object obj)//複寫equals方法
	{

		if(!(obj instanceof Person))
			return false;

		Person p = (Person)obj;
		System.out.println(this.name+"...equals.."+p.name);

		return this.name.equals(p.name) && this.age == p.age;
	}

	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

TreeSet

    可以對Set集合中的元素進行排序,底層資料結構是二叉樹。

    保證元素唯一性的依據:compareTo方法return 0.

    TreeSet排序的第一種方式:讓元素自身具備比較性,元素需要實現Comparable介面,覆蓋compareTo方法。這種方式也成為元素的自然順序,或者叫做預設順序。

    TreeSet的第二種排序方式。當元素自身不具備比較性時,或者具備的比較性不是所需要的,這時就需要讓集合自身具備比較性。在集合初始化時,就有了比較方式,接受實現Comparator介面的子類物件

    第一種方式:實現Comparable介面

class Person implements Comparable<Person> {
	private String name;
	private int age;
	public Person() {
	}
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int compareTo(Person p) {
		int num = p.age - this.age;
		//年齡相同的時比較姓名是否相同
		int num2 = (num == 0) ? this.name.compareTo(p.name) : num;
		return num2;
	}
}

第二種方式:接受實現Comparator介面的子類物件

TreeSet ts = new TreeSet(MyCompare);
//定義一個類,實現Comparator介面,覆蓋compare方法。
class MyComart implements Comparator
{
	public int compare(Object o1,Object o2)//覆蓋compare方法。
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num==0)
		{
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));//比較年齡因為Intege已經具有比較性了.直接比就可以
			
			/*
			if(s1.getAge()>s2.getAge())
				return 1;
			if(s1.getAge()==s2.getAge())
				return 0;
			return -1;
			*/
		}
		return num;
	}
}

    注:當元素自身不具備比較性,或者具備的比較性不是所需要的,這時需要讓容器自身具備比較性,定義了比較器,將比較器物件作為引數傳遞給TreeSet集合的建構函式。當兩種排序都存在時,以比較器為主。

個人總結

    集合是一個大的重點,才開始看視訊的時候總是分不清他們的特有屬性。每個分支裡面又有小的分支,多多敲程式碼與多多看筆記加深印象,好在實用的過程中明白到底用哪個最好。