概述

java的基础集合类主要都在java.util包中,基础类在java.util中,并发类在java.util.concurrent中。这里只涉及java.util包中的基础类,并发类在下一篇中介绍。

基础类包含实现了Map、List、Set、Collection、Queue、Deque、SortedMap、SortedSet、NavigableMap、NavigableSet接口的实现类。下面依次说明各个实现类的使用。

Map家族

实现了Map接口的类有HashMap、HashTable、AbstractMap、LinkedHashMap、IdentityHashMap、WeakHashMap以及继承了AbstractMap的TreeMap和EnumMap。

HashMap

HashMap用于存放key-value对,它实现了Map的所有接口,并且允许key、value为null。HashMap不能维持键值对的顺序,在运行过程中可能会改变。
其特性如下:
1. HashMap的存取时间恒定。
2. 影响其性能的参数有两个: capacity和loadFactor。
capacity是实例化时指定的容量,loadFactor是负载因子。负载因子的作用是在HashMap中的key-value对超过loadFactor*capacity的大小时,将自动重建,并且重建后size大约为重建前的2倍。所以在实例化时最好先根据需要存储的最大key-value数量小于loadFactor*capacity来设置初始容量,避免重建操作。loadFactor默认为0.75(推荐值)。使用HashMap的无参构造函数实例化的对象默认的capacity为16。(当存储的key-value对数量远大于16时,应杜绝使用HashMap的无参构造函数来实例化对象,否则随着数量逐渐增加会经常重新散列而影响性能
3. 迭代器。HashMap类的所有迭代器视图都是故障快速抛出的。避免在未来不确定时刻的不确定行为。

注意
1. 当使用很多具有相同hashCode的key对象时,会降低HashMap的性能,改良这类应用性能的方法是使用Comparable的key,HashMap将使用key的compareTo而不是hashCode来区分key。
2. HashMap是线程不安全的实现。当用于多线程应用时,必须由外部代码来实现线程同步。或者使用Collections.synchronizedMap方法来创建HashMap:

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

常用的方法:

  1. new HashMap(int capacity);
  2. HashMap.put();
  3. HashMap.get();

HashTable

HashTable的功能与HashMap大致相同。不再赘述。它与HashMap的差异有:

  • HashTable是线程安全的。
  • HashTable不允许key、value为null。
  • HashTable使用的key对象必须实现hashCode和equals方法。它们将被作为区分key的条件。
  • HashTable处理了线程的同步执因而行性能低于HashMap。

AbstractMap

AbstractMap是Map的抽象实现类,HashMap就是继承于AbstractMap抽象类的。AbstractMap实现了Map接口的骨架,它减少了实现Map子类的工作量。在继承AbstractMap实现Map子类的时候需要基于以下原则:

  • 要实现不可更改的Map时,只需实现entrySet方法,其获取的集合视图不应该实现add和remove方法,其迭代器也不应该实现remove方法。
  • 要实现可更改的Map时,除entrySet外,还需覆盖put方法(否则将抛出UnsupportedOperationException异常)。entrySet().iterator()返回的迭代器还需实现remove方法。
  • 一般需要提供一个无参构造函数和map构造函数。

LinkedHashMap

LinkedHashMap相对于HashMap具有确定迭代序列。内部使用一个双向链表来实现。其特性如下:
1. 迭代的序列就是插入序列。
2. 可以实现输入的杂乱无章的HashMap或HashTable的副本(使用LinkedHashMap的Map参构造函数实例化),并且与TreeMap关联时不会增加额外的开销。非常适合于保持与客户端输入序列顺序的输出场合。
3. 当使用LinkedHashMap(int,float,boolean)构造函数来实例化时,可选择迭代序列的模式(插入模式或访问模式)。访问模式的迭代序列是最后访问的条目从最近最少访问到最近最多访问。该模式适用于实现LRU算法。
4. 允许null元素。
5. 其他性能及影响同HashMap。也是线程不安全的实现。


IdentityHashMap

IdentityHashMap是一个机遇引用相等策略的HashMap(其他几乎都是机遇对象相等)。其判断两个key相等是这两个key的引用相同,即同一个对象。而HashMap的判断方式则是对象的内容相同。其特性如下:
1. 该实现不作为通用目的使用,现实的应用场景极少。一个典型的用法是保留拓扑结构图转换。
2. 有一个影响性能的可调参数:expected maximum size(相当于HashMap的capacity)。
3. 其他性能同HashMap。也是线程不安全的实现。


WeakHashMap

WeakHashMap中的key不再使用时,其对应的条目会被自动删除,由GC回收。该map中存储的是key的弱引用,map内部和外部的key的引用都是弱引用,都将被GC回收。其特性如下:
1. key的equals方法使用“==”来识别对象。
2. 当key被删除后,获取key的值将返回null。
3. key弱引用存储。value是强引用(当value中需要引用key对象时,key对象作为强引用而不会被GC,可使用WeakReference类包装value来解除强引用)。
4.其他性质同HashMap,也是线程不安全的实现。


TreeMap

TreeMap是基于红黑树的NavigableMap(SortedMap) map实现。TreeMap是排序映射。与HashMap不同,TreeMap没有capacity参数,它的条目总数随着插入数量增加而增加。其特性如下:
1. 根据构造函数的参数(无参或Comparator)使用插入key的自然顺序或Comparator进行排序。使用无参构造时,要求其key的类实现Comparable接口。
2. containsKey()、get()、put()、remove()操作时间复杂度为log(n)。
3. 其key必须保证相等一致性。
4. 该实现是线程不安全的。在多线程下若无外部锁对象保护,可使用Collections.synchronizedSortedMap(new TreeMap(…))创建。
5. 该类的所有集合视图方法是fail-fast的。
6. 该类方法返回的所有Map.Entry对及其视图仅是映射的当前快照,不支持使用Entry.setValue修改键值,但允许TreeMap.put方法修改。

**注意:**Map接口是依据对象的equals方法来辨识key,而SortMap是依据对象的compareTo或compare方法辨识。


EnumMap

与其他Map类不同,EnumMap使用枚举类型对象作为key。一个EnumMap中所有的key必须是来自单个枚举类。EnumMap内部是一个数组。所以非常高效。其特性如下:
1. EnumMap按照自然顺序操作它的key。keySet()、entrySet()、values()生成的集合视图反映了这种顺序。
2. 集合视图返回的迭代器是弱一致性的,在迭代器执行过程中,map被修改可能会也可能不会产生影响。并且不会抛出ConcurrentModificationException异常。
3. 不允许null作为key。插入null key将抛出NullPointerException异常。运行null作为value。
4. 该实现是线程不安全的。若外部无锁对象保护,在多线程环境下可使用Collections.synchronizedMap(new EnumMap