HashMap,LinkedHashMap和Hashtable类的深入剖析与理解

来源:互联网 发布:37轩辕剑祥云进阶数据 编辑:程序博客网 时间:2024/05/16 05:36

上一篇文章写了一些关于HashMap以及HashMap的线程安全问题,这篇文章再来说说Map系列中HashMap,LinkedHashMap和Hashtable三者之间的差异以及该注意的地方。

HashMap的该注意的地方就不赘述了,上一篇已经描述过了。

一,LinkedHashMap的知识点


从类名上理解,这个类是个链表HashMap,这个类继承了HashMap,重写了父类的一些方法。关于LinkedHashMap,有以下注意的地方:

  1. LinkedHashMap的初始默认容量为16,载入因子为0.75(继承与HashMap)

  2. LinkedHashMap不支持线程安全

  3. LinkedHashMap允许key和value为null

  4. LinkedHashMap是个双链表,遵循先进先出原则

二,Hashtable的知识点


这个类继承了Dictionary类,并且也实现了Map和Cloneable,Serializable接口,也就是说,这个类可以被克隆,也可以被序列化,这个类有以下注意的地方:

  1. Hashtable的初始默认容量为16,载入因子为0.75

  2. Hashtable是线程安全的

  3. Hashtable不允许key或者value为null

  4. 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.afterEntry<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;        }    }

0 0
原创粉丝点击