Java Collections复习笔记

来源:互联网 发布:dota6.83c数据 编辑:程序博客网 时间:2024/05/18 19:41

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());

  }

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