LinkedHashMap

    一、双向链表结构

    jdk1.8的链表结构和1.7的差异很大,可以看出来1.8中的实现简化了不是,只维护了两个指针,befor和after。在整个链表中维护了head(头指针)和tail(尾指针)。这两个指针是有讲究的,head所指向的是eldest元素,也就是最老的元素,tail指向youngest元素,也就是最年轻的元素。在这个链表中,都是在队尾添加元素,队头删除元素,这种方式很像队列,但是还是有点区别。

    1. final boolean accessOrder;
    2. public LinkedHashMap(int initialCapacity,
    3. float loadFactor,
    4. boolean accessOrder) {
    5. super(initialCapacity, loadFactor);
    6. this.accessOrder = accessOrder;
    7. }

    三、get获取元素

    LinkedHashMap的get方法几乎就是复用了HashMap。唯一的区别就是多了一个accessOrder判断,如果accessOrder==true说明他需要维护元素的访问顺序,而afterNodeAccess是HashMap提供的回调方法,他也会在put元素的时候调用。afterNodeAccess方法的作用就是将当前访问的元素添加到队尾,因为这个链表都是从头部删除,因此这个元素会在最后才被删除。

    1. // 在插入元素以后,判断当前容器的元素是否已满,如果是的话,就删除当前最老的元素,也就是队头元素。
    2. void afterNodeInsertion(boolean evict) {
    3. LinkedHashMap.Entry<K,V> first;
    4. if (evict && (first = head) != null && removeEldestEntry(first)) {
    5. K key = first.key;
    6. removeNode(hash(key), key, null, false, true);
    7. }
    8. // 这是用户实现的回调方法,判断当前最老的元素是否需要删除,如果为true,就删除链表头元素
    9. protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
    10. }

    五、删除元素

    在删除元素以后,LinkedHashMap需要维护当前链表的指针,也就是双向链表的head和tail指针的指向问题

    1. abstract class LinkedHashIterator {
    2. LinkedHashMap.Entry<K,V> next;
    3. LinkedHashMap.Entry<K,V> current;
    4. int expectedModCount;
    5. LinkedHashIterator() {
    6. // 第一次从头开始遍历
    7. next = head;
    8. expectedModCount = modCount;
    9. current = null;
    10. }
    11. public final boolean hasNext() {
    12. return next != null;
    13. }
    14. final LinkedHashMap.Entry<K,V> nextNode() {
    15. if (modCount != expectedModCount)
    16. throw new ConcurrentModificationException();
    17. if (e == null)
    18. throw new NoSuchElementException();
    19. current = e;
    20. next = e.after;
    21. return e;
    22. }
    23. public final void remove() {
    24. Node<K,V> p = current;
    25. if (p == null)
    26. throw new IllegalStateException();
    27. if (modCount != expectedModCount)
    28. throw new ConcurrentModificationException();
    29. current = null;
    30. K key = p.key;
    31. removeNode(hash(key), key, null, false, false);
    32. expectedModCount = modCount;