Map是Java容器的又一长老,映射表(也称为关联数组),基本思想是维护一对键-值对,通过键来查找值。
标准Java类库中包含Map的几种基本实现,包括:HashMap,TreeMap,LinkedHashMap,WeakHashMap,ConcurrentHashMap,IdentityHashMap,他们之间各自有一个自己的特性。
- HashMap:HashMap采用特殊的形式进行存储,这种形式被称为散列码,通过HashMap的实现可以看出,HashMap保存了一个数组,在插入数据的时候,同一个Key可以有一个固定的HashCode,通过这个HashCode将<K,V>这样的键值对映射到数组对应的位置,当然在采用这种散列码映射的时候难免会产生冲突,所以数组的每一个位置相当于指向了一个链表,当多个Key映射到同一个hashCode的时候,就要通过equals和==来比较key,所以这样在查找时的效率是相当快的。可以通过构造器设置容量和负载因子,以调整容器的性能。从迭代方法上来说,HashMap有两种迭代方式,一种是根据HashMap内部的HashIterator进行迭代,也就是对HashMap.Entry进行迭代;而另一种方法HashMap提供了一个KeySet功能,让使用者可以通过遍历Key来进行迭代。
- LinkedHashMap:类似于HashMap,但是迭代便利他时,取得“键值对”的顺序是插入次序,或者是最近最少使用(LRU)次序。只比HashMap慢一点;而在迭代访问时HashMap相当于是对数组的遍历,而LinkedHashMap是对一个链表的遍历,因为它使用链表来维护内部次序。从内部结构来说LinkedHashMap继承于HashMap又重新实现了自己的Entry和Iterator,这样就具有了上面的功能。
- TreeMap:基于AVL Tree(也叫平衡树或者红黑树)的实现。查看“键”或“键值对”时,他们会被排序(次序由Comparable或Comparator决定)。TreeMap的特点在于,所得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
- WeakHashMap, 弱键(weak key)映射,允许释放映射所指的对象;这是为解决某类特殊问题而设计的。如果映射之外没有引用指向某个“键”,则此“键”可被垃圾回收器回收。
- ConcurrentHashMap,一种线程安全的Map,他不涉及同步加锁。
- IdentityHashMap,使用==代替equals对“键”进行比较的散列映射。
Set,大概看了一些Set的实现类,如HashSet,TreeSet,发现Set其实是基于Map来搭建的,如果你了解了Map的结构那你就知道Set是怎么回事儿了,看了jdk的源码就会知道,原来所谓的Set都是由Map构成的,只不过Map是通过<Key,Value>的形式存储,而Set中的Value都指向同一个对象,jdk中给他起名叫PRESENT(替代者),这样就不会造成太大的空间浪费了。
HashSet的实现
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; //内部结构的维护使用的HashMap // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); /** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<E,Object>(); }…… 而LinkedHashSet继承自HashSet,
再看一下TreeSet
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable { /** * The backing map. */ private transient NavigableMap<E,Object> m; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); /** * Constructs a set backed by the specified navigable map. */ TreeSet(NavigableMap<E,Object> m) { this.m = m; }