1. 程式人生 > 其它 >集合基礎詳解

集合基礎詳解

Iterable 介面

  • Iterable是一個超級介面,被Collection所繼承。它只有一個方法: Iterator iterator() //即返回一個迭代器

  • Java中的Iterator功能比較簡單,並且只能單向移動
    (1) 使用方法iterator()要求容器返回一個Iterator。第一次呼叫Iterator的next()方法時,它返回序列的第一個元素。注意:iterator()方法是java.lang.Iterable介面,被Collection繼承。
      (2) 使用next()獲得序列中的下一個元素。
      (3) 使用hasNext()檢查序列中是否還有元素。
      (4) 使用remove()將迭代器新返回的元素刪除。

Collection 介面

JDK 不提供此介面的任何直接 實現:它提供更具體的子介面(如 Set 和 List)實現。

不同的Collection子類對於有序性、重複性、null、執行緒同步都有不同的策略。

List 介面

  • List是有序的 collection(也稱為序列)。此介面的使用者可以對列表中每個元素的插入位置進行精確地控制。使用者可以根據元素的整數索引(在列表中的位置)訪問元素,並搜尋列表中的元素。

  • 使用者插入的順序或者指定的位置就是元素插入的位置。它與Set不同,List允許插入重複的值

  • List 介面提供了特殊的迭代器,稱為 ListIterator,除了允許 Iterator 介面提供的正常操作外,該迭代器還允許元素插入

    替換,以及雙向訪問。還提供了一個方法(如下)來獲取從列表中指定位置開始的列表迭代器。

    ListIterator <E> listIterator(int index)
    返回列表中元素的列表迭代器(按適當順序),從列表的指定位置開始
    
  • List 介面提供了兩種搜尋指定物件的方法。從效能的觀點來看,應該小心使用這些方法。在很多實現中,它們將執行高開銷的線性搜尋。

  • List 介面提供了兩種在列表的任意位置高效插入和移除多個元素的方法。

List的子類

  • List最流行的實現類有Vector、ArrayList、LinkedList。

1、 ArrayList (類)

  1. ArrayLis是基於陣列實現的List類,它封裝了一個動態的、增長的、允許再分配的
    Object[ ]陣列.它允許對元素進行快速隨機訪問(ArrayList每次擴容自身的1.5倍
  2. 當從ArrayList的中間位置插入或者刪除元素時,需要對陣列進行復制、移動、代價比較高。因此,它適合隨機查詢和遍歷,不適合插入和刪除。

2、Vector(類)

Vector與ArrayList一樣,也是通過陣列實現的,不同的是它支援執行緒的同步,即某一時刻只有一個執行緒能夠寫Vector,避免多執行緒同時寫而引起的不一致性,但實現同步需要很高的花費,因此,訪問它比訪問ArrayList。所以現在已經不太常用了。

2.1、Stack(類)

Stack是Vector提供的一個子類,用於模擬"棧"這種資料結構(LIFO後進先出)

3、LinkedList (類)

  1. LinkedList是用連結串列結構儲存資料的,很適合資料的動態插入和刪除,隨機訪問和遍歷速度比較慢。
  2. 另外,它還實現了Deque介面,專門用於操作表頭和表尾元素,可以當作堆疊、佇列和雙向佇列使用。
名稱 擴容方式(預設) 執行緒安全 速度 有效個數的屬性
ArrayList 增長50% 執行緒不安全 size
Vector 增長一倍 執行緒安全 elementCount
共同點 如果新增的有效元素個數超過陣列本身的長度,都會導致陣列進行擴容 - remove,add(index,obj)方法都會導致內部陣列進行資料拷貝的操作,這樣在大資料量時,可能會影響效率 -

其他

List介面的排序可以通過Collections.sort()來進行定製排序
只需要繼承Comparable介面後,重寫compareTo()方法。

public class Student extends Thread implements Comparable {	
	private int age;
	private String name;
	private String tel;
	private int height;

	public Student( String name,int age, String tel, int height) {
		this.age = age;
		this.name = name;
		this.tel = tel;
		this.height = height;
	}

	public static void main(String args[]) throws InterruptedException{
		Student stu1 = new Student("張三",21,"156482",172);
		Student stu2 = new Student("李四",18,"561618",168);
		Student stu3 = new Student("王五",19,"841681",170);
		Student stu4 = new Student("趙七",20,"562595",180);
   	
		List<Student> list = new ArrayList<Student>();
		//亂序插入
		list.add(stu3);
		list.add(stu1);
		list.add(stu4);
		list.add(stu2);
   	
		System.out.println("-----------排序前----------");
		Iterator<Student> it = list.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
        
		/*
		* 使用Collections的sort方法讓集合排序,使用其方法必須要重寫
		* Comparable介面的compareTo()方法
		* */
		Collections.sort(list);
		System.out.println("-----------按照年齡排序後----------");
		for(int i=0;i<list.size();i++){
			System.out.println(list.get(i).toString());
		}
	}

	//重寫compareTo方法,用age來比較。也可以用別的來比較
	@Override
	public int compareTo(Object o) {
		//使用當前物件的年齡和其他物件的年齡比較,如果<0返回負數,>0返回正數,=0返回0
		int z = this.age - ((Student)o).getAge();
		if(z<0) 
			return -1;  // 返回其他負數也行
		else if(z == 0) 
			return 0;
		else 
			return 1;  //返回其他正數也行
	}
   
   //重寫toString,便於輸出
	@Override
	public String toString(){
		return name+","+age+","+tel+","+height;
	}
}

Set介面

  • Set,顧名思義,集合的意思。java的集合和數學的集合一樣,滿足集合的無序性,確定性,單一性。同時,如果有多個null,則不滿足單一性了,所以Set只能有一個null
  • Set判斷兩個物件相同不是使用"=="運算子,而是根據equals方法。也就是說,我們在加入一個新元素的時候,如果這個新元素物件和Set中已有物件進行注意equals比較都返回false,則Set就會接受這個新元素物件,否則拒絕。
    ——因為Set的這個制約,在使用Set集合的時候,應該注意兩點:
    1、為Set集合裡的元素的實現類實現一個有效的equals(Object)方法;
    2、對Set的建構函式,傳入的Collection引數不能包含重複的元素。

Set的子類/子介面

  • Set最流行的實現類有HashSet、TreeSet、LinkedHashSet(從HashSet繼承而來)。

1、 HashSet (類)

  • HashSet是Set介面的典型實現,HashSet使用HASH演算法來儲存集合中的元素,因此具有良好的存取和查詢效能。當向HashSet集合中存入一個元素時,HashSet會呼叫該物件的 hashCode()方法來得到該物件的hashCode值,然後根據該HashCode值決定該物件在HashSet中的儲存位置。
  • 值得主要的是,HashSet集合判斷兩個元素相等的標準是兩個物件通過equals()方法比較相等,並且兩個物件的hashCode()方法的返回值相等

1.1、LinkedHashSet(類)

  • LinkedHashSet集合也是根據元素的hashCode值來決定元素的儲存位置,但和HashSet不同的是,它同時使用連結串列維護元素的次序,這樣使得元素看起來是以插入的順序儲存的。
  • 當遍歷LinkedHashSet集合裡的元素時,LinkedHashSet將會按元素的新增順序來訪問集合裡的元素。
  • LinkedHashSet需要維護元素的插入順序,因此效能略低於HashSet的效能,但在迭代訪問Set裡的全部元素時(遍歷)將有很好的效能(連結串列很適合進行遍歷)

2、SortedSet (介面)

  • 此介面主要用於排序操作,實現了此介面的子類都屬於排序的子類

2.1、TreeSet(類)

  • TreeSet是SortedSet介面的實現類,TreeSet可以確保集合元素處於排序狀態

3、EnumSet (類)

  • EnumSet是一個專門為列舉類設計的集合類,EnumSet中所有元素都必須是指定列舉型別的列舉值,該列舉型別在建立EnumSet時顯式或隱式地指定。EnumSet的集合元素也是有序的,

Queue介面

  • 此介面用於模擬“佇列”資料結構(FIFO)。新插入的元素放在隊尾,隊頭存放著儲存時間最長的元素。

Queue的子類/子介面

1、PriorityQueue—— 優先佇列(類)

  • 其實它並沒有按照插入的順序來存放元素,而是按照佇列中某個屬性的大小來排列的。故而叫優先佇列。

2、Deque——雙端佇列(介面)

2.1、ArrayDeque(類)

  • 基於陣列的雙端佇列,類似於ArrayList有一個Object[] 陣列。

2.2、LinkedList (類)(上文已有)

上述三個介面的區別:

容器名 是否有序 是否可重複 null的個數
List 有序 可重複 允許多個null
Set 無序 不可重複 只允許一個null
Queue 有序(FIFO) 可重複 通常不允許插入null

Map 介面

  • Map不是collection的子介面或者實現類。Map是一個介面。

  • Map用於儲存具有“對映關係”的資料。每個Entry都持有鍵-值兩個物件。其中,Value可能重複,但是Key不允許重複(和Set類似)。

  • Map可以有多個Value為null,但是隻能有一個Key為null。

Map的子類/子介面

1、HashMap (類)

  • 和HashSet集合不能保證元素的順序一樣,HashMap也不能保證key-value對的順序。並且類似於HashSet判斷兩個key是否相等的標準一樣: 兩個key通過equals()方法比較返回true、 同時兩個key的hashCode值也必須相等

1.1、LinkedHashMap (類)

  • LinkedHashMap也使用雙向連結串列來維護key-value對的次序,該連結串列負責維護Map的迭代順序,與key-value對的插入順序一致(注意和TreeMap對所有的key-value進行排序區分)。

2、HashTable (類)

是一個古老的Map實現類。

2.1、Properties(類)

  • Properties物件在處理屬性檔案時特別方便(windows平臺的.ini檔案)。Properties類可以把Map物件和屬性檔案關聯,從而把Map物件的key - value對寫入到屬性檔案中,也可把屬性檔案中的“屬性名-屬性值”載入進Map物件中。

3、SortedMap(介面)

如同Set->SortedSet->TreeSet一樣,Map也有Map->SortedMap->TreeMap的繼承關係。

3.1、TreeMap(類)

  • TreeMap是一個紅黑樹結構,每個鍵值對都作為紅黑樹的一個節點。TreeMap儲存鍵值對時,需要根據key對節點進行排序,TreeMap可以保證所有的key-value對處於有序狀態。 同時,TreeMap也有兩種排序方式:自然排序、定製排序(類似於上面List的重寫CompareTo()方法)。

4、WeakHashMap(類)

  • 看名字就能發現,這是Weak後的HashMap。但是二者大體差別不大。
  • 區別在於,HashMap的key保留了對實際物件的強引用,這意味著只要該HashMap物件不被銷燬,該HashMap所引用的物件就不會被垃圾回收。
  • 但WeakHashMap的key只保留了對實際物件的弱引用,這意味著如果WeakHashMap物件的key所引用的物件沒有被其他強引用變數所引用,則這些key所引用的物件可能被垃圾回收,當垃圾回收了該key所對應的實際物件之後,WeakHashMap也可能自動刪除這些key所對應的key-value對

5、IdentityHashMap(類)

  • 這個類也和HashMap類似,區別在於,在IdentityHashMap中,當且僅當兩個key嚴格相等(key1==key2)時,IdentityHashMap才認為兩個key相等

  • IdentityHashMap不是Map的通用實現,它有意違反了Map的常規協定。並且IdentityHashMap允許key和value都為null。

  • 同HashMap,IdentityHashMap也是無序的,並且該類不是執行緒安全的,如果要使之執行緒安全,可以呼叫Collections.synchronizedMap(new IdentityHashMap(…))方法來實現。

6、EnumMap(類)

  • EnumMap是一個與列舉類一起使用的Map實現,EnumMap中的所有key都必須是單個列舉類的列舉值。建立EnumMap時必須顯式或隱式指定它對應的列舉類。EnumMap根據key的自然順序儲存。