首页 > 代码库 > HashMap,LinkedHashMap和Hashtable类的深入剖析与理解
HashMap,LinkedHashMap和Hashtable类的深入剖析与理解
上一篇文章写了一些关于HashMap以及HashMap的线程安全问题,这篇文章再来说说Map系列中HashMap,LinkedHashMap和Hashtable三者之间的差异以及该注意的地方。
HashMap的该注意的地方就不赘述了,上一篇已经描述过了。
一,LinkedHashMap的知识点
从类名上理解,这个类是个链表HashMap,这个类继承了HashMap,重写了父类的一些方法。关于LinkedHashMap,有以下注意的地方:
LinkedHashMap的初始默认容量为16,载入因子为0.75(继承与HashMap)
LinkedHashMap不支持线程安全
LinkedHashMap允许key和value为null
LinkedHashMap是个双链表,遵循先进先出原则
二,Hashtable的知识点
这个类继承了Dictionary类,并且也实现了Map和Cloneable,Serializable接口,也就是说,这个类可以被克隆,也可以被序列化,这个类有以下注意的地方:
Hashtable的初始默认容量为16,载入因子为0.75
Hashtable是线程安全的
Hashtable不允许key或者value为null
Hashtable的操作使用了synchronized来达到线程安全问题,连entrySet()方法中也用了Collections.synchronizedSet(),但是还是避免不了Iterator的快速失败,因此,在有迭代器操作时,一定要注意。
三,HashMap和LinkedHashMap的关键点
其实LinkedHashMap的关键功能就是为了保证插入的数据的顺序问题。由于LinkedHashMap是双链表结构,那这样导致每次插入的数据都是由指针顺序指向的,因此取数据时,也就是顺序取了,如果你的结合大多数情况下,在copy时还要保证顺序不变,那么LInkedHashMap是个很好的选择;而HashMap由于是通过hash来存储在Hash表中的值来查找数据的,而hash值又是随机的,这样导致存入的数据顺序和取出来的数据顺序是不同的,下面分别是LinkedHashMap和HashMap的取数据的源码,一看便知:
private abstract class LinkedHashIterator<T> implements Iterator<T> { Entry<K,V> nextEntry = header.after; Entry<K,V> lastReturned = null; /** * The modCount value that the iterator believes that the backing * List should have. If this expectation is violated, the iterator * has detected concurrent modification. */ int expectedModCount = modCount; public boolean hasNext() { return nextEntry != header; } public void remove() { if (lastReturned == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); LinkedHashMap.this.remove(lastReturned.key); lastReturned = null; expectedModCount = modCount; } //注意点就在这里e.after Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (nextEntry == header) throw new NoSuchElementException(); Entry<K,V> e = lastReturned = nextEntry; nextEntry = e.after; return e; } }
HashMap:
private abstract class HashIterator<E> implements Iterator<E> { Entry<K,V> next; // next entry to return int expectedModCount; // For fast-fail int index; // current slot Entry<K,V> current; // current entry HashIterator() { expectedModCount = modCount; if (size > 0) { // advance to first entry Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } } public final boolean hasNext() { return next != null; } //可以看到,HashMap的取值是从hash表中通过表索引取的,而这个hash表的数据顺序已经在put的时候存储好了 final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); Entry<K,V> e = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; } public void remove() { if (current == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); Object k = current.key; current = null; HashMap.this.removeEntryForKey(k); expectedModCount = modCount; } }