//重写的addEntry。其中还是会调用父类中的addEntry方法,但是此外会增加额外的功能,
void addEntry(int hash, K key, V value, int bucketIndex) {
super.addEntry(hash, key, value, bucketIndex);
// Remove eldest entry if instructed
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
}
}
//HashMap的addEntry,就是在将元素加入桶中前判断桶中的大小或者数组的大小是否合适,总之就是做一些数组容量上的判断和hash值的问题。
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
//这里就是真正创建entry的时候了。也被LinkedHashMap重写了。
createEntry(hash, key, value, bucketIndex);
}
//重写的createEntry,这里要注意的是,新元素放桶中,是放第一位,而不是往后追加,所以下面方法中前面三行应该知道了
void createEntry(int hash, K key, V value, int bucketIndex) {
HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<>(hash, key, value, old);
table[bucketIndex] = e;
//这个方法的作用就是将e放在双向循环链表的末尾,需要将一些指向进行修改的操作。。
e.addBefore(header);
size++;
}
到这里,应该就对LinkedHashMap的存储过程有一定的了解了。并且也应该知道是如何存储的了。存储时有何特殊之处。
2.5、来看看迭代器的使用。对双向循环链表的遍历操作。但是这个迭代器是abstract的,不能直接被对象所用,但是能够间接使用,就是通过keySet().interator(),就是使用的这个迭代器
//这个也非常简单,无非就是对双向循环链表进行遍历。 private abstract class LinkedHashIterator<T> implements Iterator<T> { //先拿到header的after指向的元素,也就是第一个元素。 Entry<K,V> nextEntry = header.after; //记录前一个元素是谁,因为刚到第一个元素,第一个元素之前的元素理论上就是null。实际上是指向最后一个元素的。知道就行。 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; //判断有没有到循环链表的末尾,就看元素的下一个是不是header。 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; } //下一个元素。一些指向问题,度是双向循环链表中的操作。 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; } }
keySet()是如何间接使用了LinkedHashIterator的
hashMap中的keySet()
找到newKeyIterator()
是LinkedHashMap对象调用的,而LinkedHashMap中重写了KeyIterator方法,所以就这样间接的使用了LinkedHashIterator迭代器
2.6、看看迭代时使用访问顺序如何实现的,其实关键也就是在哪个recordAccess方法,来看看流程
linkedHashMap中有get方法,不会使用父类中的get方法