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;
}
}