Java Collections複習筆記

List

ArrayList

可增長的數組

Fast iteration

Fast random access

Ordered (by index)

Unsorted

Not efficient for insertion/deletion

Vector

Thread-safe

Random Access (Only ArrayList and Vector have this property)

LinkedList

Sorted (by index)

Elements are double-linked

Also implements Queue interface, has peek(), poll(), offer()methods

Maybe a little bit slower than ArrayList when iterating, butmuch faster for insertion/deletion

 

Set

Ensure uniqueness 

HashSet

Unordered, unsorted

The more efficient hashcode() is, the more efficient HashSetis.

If you don’t need or don’t allow duplicates, and don’t care aboutsequence when iterating the set, you can use HashSet.

HashSet has quick insertion/deletion, requires least expensecompared to other Set collections.

LinkedHashSet

Ordered HashSet

Elements are double-linked

If you care about the sequence when iterating elements, youshould use LinkedHashSet instead of HashSet. LinkedHashSet iterates elementsusing the insertion sequence.

TreeSet

Sorted

保證排序後的set按照升序排列元素,根據使用constructor的不同,可能會按照元素的自然順序進行排序,或按照創建set時所提供的comparator進行排序。

TreeSet has 4 constructors:

1.    TreeSet()

構造一個新的空set,按照元素的自然順序排序

2. TreeSet(Collection<? extends E> c)

構造一個新的set,包含指定collection中的元素,按照元素的自然順序排序

3. TreeSet(Comparator<? super E> c)

構造一個新的空set,根據指定的comparator進行排序

4. TreeSet(SortedSet<E> s)

構造一個新set,該set所包含的元素與指定的已排序set包含的元素相同,並按照相同的順序對元素進行排序。

 

Map

Unique ID

Support key/value pair

與Set一樣,Map依賴於equals()方法來判斷兩個鍵是否相同

Based on red-black tree

HashMap

Unordered, unsorted

The more efficient hashcode() is, the more efficient HashMapis.

If you need a Map, and don’t care about sequence wheniterating the map, you can use HashMap. All other collections will requireextra expenses.

HashMap allows one NULL key and many NULL values.

Hashtable

Thread-safe

Hashtable doesn’t allow any NULL key or NULL value. 

LinkedHashMap

LinkedHashMap iterates in insertion sequence

It is slower than HashMap when insertion or deletion, butfaster when iterating. 

TreeMap

Sorted

保證映射按照升序排列關鍵字,根據使用constructor的不同,可能會按照元素的自然順序進行排序,或按照創建set時所提供的comparator進行排序。

TreeSet has 4 constructors:

1.   TreeMap()

構造一個新的空映射,按照元素的自然順序排序

2.  TreeMap(Comparator<?super K> c)

構造一個新的空映射,根據指定的comparator進行排序

3.   TreeMap(Map<? Extends K, ? extends V> m)

構造一個新映射,包含的映射關係與給定的映射相同,這個新映射按照鍵的自然順序進行排序

4.  TreeMap(SortedMap<K,? extends V> m)

構造一個新的映射,包含的映射關係與給定的SortedMap相同,並按照相同的排序方式進行排序。

 


Collections

Collections.synchronizedList(List)

以ArrayList爲例,如果多個線程同時訪問一個ArrayList實例,而其中至少一個線程從結構上修改了列表,那麼它就必須保持外部同步。(結構上的修改是指任何添加或刪除一個或多個元素的操作,或者顯式調整底層數組的大小;僅僅設置元素的值不是結構上的修改。)這一般通過對自然封裝該列表的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用Collections.synchronizedList方法將該列表“包裝”起來。這最好在創建時完成,以防止意外對列表進行不同步的訪問:

public static <T> List<T> synchronizedList(List<T> list)

返回由指定列表支持的同步(線程安全的)列表。爲了保證按順序訪問,必須通過返回的列表完成對底層列表的所有訪問。

 

在創建之後,除非通過Iterator自身的remove或add方法從結構上對列表進行修改,否則在任何時間以任何方式對列表進行修改,Iterator都會拋出ConcurrentModificationException。因此,面對併發的修改,Iterator很快就會完全失敗,而不是冒着在將來某個不確定時間發生任意不確定行爲的風險。

但是,Iterator的快速失敗行爲無法得到保證,因爲一般來說,不可能對是否出現不同步併發修改做出任何硬性保證。快速失敗迭代器會盡最大努力拋出 ConcurrentModificationException。因此,爲提高這類迭代器的正確性而編寫一個依賴於此異常的程序是錯誤的做法:迭代器的快速失敗行爲應該僅用於檢測bug。

 

在返回的列表上進行迭代時,強制用戶手工在返回的列表上進行同步:

List list = Collections.synchronizedList(new ArrayList());

… …

Synchronized(list){

     Iterator i = list.iterator();//Must be in synchronized block

     While(i.hasNext())

          foo(i.next());

}

如果指定列表是可序列化的,則返回的列表也將是可序列化的。

 

Collections.synchronizedSet(Set)

以HashSet爲例,如果多個線程同時訪問一個集合,而其中至少一個線程修改了該集合,那麼它必須保持外部同步。這通常是通過對自然封裝該集合的對象執行同步操作來完成的。如果不存在這樣的對象,則應該使用 Collections.synchronizedSet方法來“包裝”集合。最好在創建時完成這一操作,以防止對 HashSet 實例進行意外的不同步訪問:

public static <T> Set<T> synchronizedSet(Set<T> s)

返回由指定 set 支持的同步(線程安全的)set。爲了保證按順序訪問,必須通過返回的set 完成對底層 set 的所有訪問。

 

此類的 iterator方法返回的迭代器是快速失敗 的:在創建迭代器之後,如果對集合進行修改,除非通過迭代器自身的remove 方法,否則在任何時間以任何方式對其進行修改,Iterator都將拋出 ConcurrentModificationException。因此,面對併發的修改,迭代器很快就會完全失敗,而不冒將來在某個不確定時間發生任意不確定行爲的風險。

注意,迭代器的快速失敗行爲無法得到保證,因爲一般來說,不可能對是否出現不同步併發修改做出任何硬性保證。快速失敗迭代器在盡最大努力拋出 ConcurrentModificationException。因此,爲提高這類迭代器的正確性而編寫一個依賴於此異常的程序是錯誤做法:迭代器的快速失敗行爲應該僅用於檢測程序錯誤。

 

在返回的 set 上進行迭代時,強制用戶手工在返回的 set 上進行同步:

Set s = Collections.synchronizedSet(new HashSet());

      ...

  synchronized(s) {

      Iterator i = s.iterator(); // Must be in the synchronized block

      while (i.hasNext())

          foo(i.next());

  }

如果指定 set 是可序列化的,則返回的 set 也將是可序列化的。

 

 

此外,對於sorted Set(TreeSet),還有專門的方法

public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)

返回由指定有序 set 支持的同步(線程安全的)有序 set。爲了保證按順序訪問,必須通過返回的有序set(或其視圖)完成對底層有序 set 的所有訪問。

在返回的有序 set 上或其 subSet、headSet或 tailSet 視圖上進行迭代時,強制用戶手工在返回的有序 set 上進行同步。

SortedSet s = Collections.synchronizedSortedSet(new HashSortedSet());

      ...

  synchronized(s) {

      Iterator i = s.iterator(); // Must be in the synchronized block

      while (i.hasNext())

          foo(i.next());

  }

SortedSet s = Collections.synchronizedSortedSet(new HashSortedSet());

  SortedSet s2 = s.headSet(foo);

      ...

  synchronized(s) {  // Note: s, not s2!!!

      Iterator i = s2.iterator(); // Must be in the synchronized block

      while (i.hasNext())

          foo(i.next());

  }

如果指定 set 是可序列化的,則返回的 set 也將是可序列化的。

 

 

Collections.synchronizedMap(Map)

以HashMap爲例,如果多個線程同時訪問此映射,而其中至少一個線程從結構上修改了該映射,則它必須 保持外部同步。(結構上的修改是指添加或刪除一個或多個映射關係的操作;僅改變與實例已經包含的鍵關聯的值不是結構上的修改。)這一般通過對自然封裝該映射的對象進行同步操作來完成。如果不存在這樣的對象,則應該使用 Collections.synchronizedMap方法來“包裝”該映射。最好在創建時完成這一操作,以防止對映射進行意外的不同步訪問:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

 

返回由指定映射支持的同步(線程安全的)映射。爲了保證按順序訪問,必須通過返回的映射完成對底層映射的所有訪問。

 

由所有此類的“集合視圖方法”所返回的迭代器都是快速失敗 的:在迭代器創建之後,如果從結構上對映射進行修改,除非通過迭代器自身的 remove 或 add 方法,其他任何時間任何方式的修改,迭代器都將拋出 ConcurrentModificationException。因此,面對併發的修改,迭代器很快就會完全失敗,而不冒在將來不確定的時間任意發生不確定行爲的風險。

注意,迭代器的快速失敗行爲不能得到保證,一般來說,存在不同步的併發修改時,不可能作出任何堅決的保證。快速失敗迭代器盡最大努力拋出 ConcurrentModificationException。因此,編寫依賴於此異常程序的方式是錯誤的,正確做法是:迭代器的快速失敗行爲應該僅用於檢測程序錯誤。

 

在返回的映射或其任意 collection 視圖上進行迭代時,強制用戶手工在返回的映射上進行同步:

Map m = Collections.synchronizedMap(new HashMap());

      ...

  Set s = m.keySet();  // Needn't be in synchronized block

      ...

  synchronized(m) {  // Synchronizing on m, not s!

      Iterator i = s.iterator(); // Must be in synchronized block

      while (i.hasNext())

          foo(i.next());

  }

如果指定映射是可序列化的,則返回的映射也將是可序列化的。

 

 

此外,對於sorted Map(TreeMap),還有專門的方法

public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)

返回由指定有序映射支持的同步(線程安全的)有序映射。爲了保證按順序訪問,必須通過返回的有序映射(或其視圖)完成對底層有序映射的所有訪問。

當在返回的有序映射的任何 collection 視圖上進行迭代時,或者在其任何subMap、headMap 或 tailMap 視圖進行迭代時,強制用戶手工在該映射上進行同步:

 

SortedMap m = Collections.synchronizedSortedMap(new HashSortedMap());

      ...

  Set s = m.keySet();  // Needn't be in synchronized block

      ...

  synchronized(m) {  // Synchronizing on m, not s!

      Iterator i = s.iterator(); // Must be in synchronized block

      while (i.hasNext())

          foo(i.next());

  }

SortedMap m = Collections.synchronizedSortedMap(new HashSortedMap());

  SortedMap m2 = m.subMap(foo, bar);

      ...

  Set s2 = m2.keySet();  // Needn't be in synchronized block

      ...

  synchronized(m) {  // Synchronizing on m, not m2 or s2!

      Iterator i = s.iterator(); // Must be in synchronized block

      while (i.hasNext())

          foo(i.next());

  }

如果指定的有序映射是可序列化的,則返回的有序映射也將是可序列化的。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章