LinkedHashMap源码详解(4)

//重写的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()

                  

LinkedHashMap源码详解

  

              找到newKeyIterator()

                  

              是LinkedHashMap对象调用的,而LinkedHashMap中重写了KeyIterator方法,所以就这样间接的使用了LinkedHashIterator迭代器

                  

LinkedHashMap源码详解

2.6、看看迭代时使用访问顺序如何实现的,其实关键也就是在哪个recordAccess方法,来看看流程

linkedHashMap中有get方法,不会使用父类中的get方法

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/a25696dfd150e2968980e79cb284a56a.html