java源码分析之LinkedHashMap(三)
e >= threshold)
8 resize(2 * table.length);
9 }
10 }
首先调用createEntry(int hash,K key,V value,int bucketIndex)方法,之后获取LinkedHashMap中“最老”(最近最少使用)的节点,接着涉及到了removeEldestEntry(Entry eldest)方法,来看一下:
1 protected boolean removeEldestEntry(Map.Entry eldest) {
2 return false;
3 }
为什么这个方法始终返回false?
结合上面的addEntry(int hash,K key,V value,int bucketIndex)方法,这样设计可以使LinkedHashMap成为一个正常的Map,不会去移除“最老”的节点。
为什么不在代码中直接去除这部分逻辑而是设计成这样呢?
这为开发者提供了方便,若希望将Map当做Cache来使用,并且限制大小,只需继承LinkedHashMap并重写removeEldestEntry(Entry eldest)方法,像这样:
1 private static final int MAX_ENTRIES = 100;
2 protected boolean removeEldestEntry(Map.Entry eldest) {
3 return size() > MAX_ENTRIES;
4 }
LinkedHashMap除了以上内容外还有和迭代相关的三个方法及三个内部类以及一个抽象内部类,分别是:newKeyIterator()、newValueIterator()、newEntryIterator()和KeyIterator类、ValueIterator类、EntryIterator类以及LinkedHashIterator类。
三个new方法分别返回对应的三个类的实例。而三个类都继承自抽象类LinkedHashIterator。下面看迭代相关的三个类。
1 private class KeyIterator extends LinkedHashIterator {
2 public K next() { return nextEntry().getKey(); }
3 }
4 private class ValueIterator extends LinkedHashIterator {
5 public V next() { return nextEntry().value; }
6 }
7 private class EntryIterator extends LinkedHashIterator> {
8 public Map.Entry next() { return nextEntry(); }
9 }
从上面可以看出这三个类都很简单,只有一个next()方法,next()方法也只是去调用LinkedHashIterator类中相应的方法。 和KeyIterator类、ValueIterator类、EntryIterator类以及LinkedHashIterator类。
下面是LinkedHashIterator类的内容。
1 private abstract class LinkedHashIterator implements Iterator {
2 Entry nextEntry = header.after;
3 Entry lastReturned = null;
4 // 和LinkedList中ListItr类定义了expectedModCount用途一致
5 int expectedModCount = modCount;
6 // 下一个节点如果是header节点说明当前节点是链表的最后一个节点,即已经遍历完链表了,没有下一个节点了
7 public boolean hasNext() {
8 return nextEntry != header;
9 }
10 //移除上一次被返回的节点lastReturned
11 public void remove() {
12 if (lastReturned == null)
13 throw new IllegalStateException();
14 if (modCount != expectedModCount)
15 throw new ConcurrentModificationException();
16 LinkedHashMap.this.remove(lastReturned.key);
17 lastReturned = null;
18 expectedModCount = modCount;
19 }
20 // 返回下一个节点
21 Entry nextEntry() {
22 if (modCount != expectedModCount)
23 throw new ConcurrentModificationException();
24 if (nextEntry == header)
25 throw new NoSuchElementException();
26 // 获取并记录返回的节点
27 Entry e = lastReturned = nextEntry;
28 // 保存对下一个节点的引用
29 nextEntry = e.after;
30 return e;
31 }
32 }
LinkedHashMap本应和HashMap及LinkedList一起分析,比较他们的异同。为了弥补,这里简单的总结一些他们之间的异同:
HashMap使用哈希表来存储数据,并用拉链法来处理冲突。LinkedHashMap继承自HashMap,同时自身有一个链表,使用链表存储数据,不存在冲突。LinkedList和LinkedHashMap一样使用一个双向循环链表,但存储的是简单的数据,并不是“键值对”。所以HashMap和LinkedHashMap是Map,而LinkedList是一个List,这是他们本质的区别。LinkedList和LinkedHashMap都可以维护内容的顺序,但HashMap不维护顺序。