Java LinkedHashMap深入分析源码

一、LinkedHashMap的类继承关系

二、源码分析

1.自己对LinkedHashMap的理解

从继承关系上,我们看到LinkedHashMap继承了HashMap,它里面的增删改差遍历的逻辑都是使用的HashMap中的,但是LinkedHashMap比HashMap多了一个双向链,这个双向链是从第一个插入的元素开始按照插入顺序,连接起来,所以可以说LinkedHashMap是可以保证插入顺序的。

看图:这里就简单的给大家看一下这个链是啥样的,不画红黑树了

2.如何做到双向链的增删改查

(1).增

1).是在创建新节点的时候,把双向链连接起来,注意有两种节点一个是TreeNode一个普通Node

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Node newNode(int hash, K key, V value, Node e) {
    LinkedHashMap.Entry p =
        new LinkedHashMap.Entry(hash, key, value, e);
    linkNodeLast(p);
    return p;
}
TreeNode newTreeNode(int hash, K key, V value, Node next) {
    TreeNode p = new TreeNode(hash, key, value, next);
    linkNodeLast(p);
    return p;
}
private void linkNodeLast(LinkedHashMap.Entry p) {
    LinkedHashMap.Entry last = tail;
    tail = p;
    if (last == null)
        head = p;
    else {
        p.before = last;
        last.after = p;
    }
}
static class Entry extends HashMap.Node {
    Entry before, after;
    Entry(int hash, K key, V value, Node next) {
        super(hash, key, value, next);
    }
}

代码太简单了,这里简单描述一下,就是添加新节点会创建Node,有两种Node:TreeNode和普通Node(注意这里多态的使用普通Node和LinedHashMap.Entry和TreeNode的关系看一下就明白了),在创建之后放到双向链最后面。

2).有好多人说了还有一个afterNodeInsertion方法,这个方法的名字就显示是在插入之后调用的,是不是在这个方法中也有修改链表的逻辑,我们来看这个方法

1
2
3
4
5
6
7
8
9
10
void afterNodeInsertion(boolean evict) { // possibly remove eldest
    LinkedHashMap.Entry first;
    if (evict && (first = head) != null && removeEldestEntry(first)) {
        K key = first.key;
        removeNode(hash(key), key, null, false, true);
    }
}
protected boolean removeEldestEntry(Map.Entry eldest) {
    return false;
}

看这个判断,有一个永远是false,也就是说如果我们不重写这个removeEldestEntry方法,那这个afterNodeInsertion方法里的逻辑永远不会执行,那这个玩意儿是干啥的呢,看逻辑是用来移除最早的头节点的,不知道为啥写着么一段,默认不会执行!!!

(2).删

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void afterNodeRemoval(Node e) { // unlink
    LinkedHashMap.Entry p =
            (LinkedHashMap.Entry)e, b = p.before, a = p.after; // b是当前节点的前一个节点,a是后一个节点
    p.before = p.after = null; //先断开当前节点,把当前节点对上一个和下一个节点的引用置为空
    if (b == null) //当前节点的前一个节点是null,说明当前节点是头节点,那去掉当前节点之后,当前节点的后一个节点成为了链第一个,
        // 也就是头节点,当然有可能a也是null,那整个链就是空链,这种写法兼容了a也是null的情况
        head = a;
    else
        b.after = a; //如果当前节点不是头节点,直接去掉当前节点,当前节点的前一个和后一个连起来
    if (a == null) //如果当前节点的后一个节点是null,说明当前节点是尾节点,那把当前节点去掉后,当前节点的前一个节点成为了链的最后一个节点尾节点。
        tail = b;
    else
        a.before = b;//如果当前节点不是尾节点,直接去掉当前节点,当前节点的前一个和后一个连起来
}

这个删除我们看一下在哪里调用的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
final Node removeNode(int hash, Object key, Object value,
                           boolean matchValue, boolean movable) {
        ...
        if (node != null && (!matchValue || (v = node.value) == value ||
                             (value != null && value.equals(v)))) {
            if (node instanceof TreeNode)
                ((TreeNode)node).removeTreeNode(this, tab, movable);
            else if (node == p)
                tab[index] = node.next;
            else
                p.next = node.next;
            ++modCount;
            --size;
            afterNodeRemoval(node); //<img draggable="false" role="img" class="emoji" alt="⭐️" src="https://s.w.org/images/core/emoji/15.1.0/svg/2b50.svg"><img draggable="false" role="img" class="emoji" alt="⭐️" src="https://s.w.org/images/core/emoji/15.1.0/svg/2b50.svg"><img draggable="false" role="img" class="emoji" alt="⭐️" src="https://s.w.org/images/core/emoji/15.1.0/svg/2b50.svg">
            return node;
        }
    }
    return null;
}

在HashMap的removeNode方法里,当时学习HashMap的时候还是有疑惑的这个方法干啥使的,还是一个没有方法体的空实现方法,现在明白了,就是在给子类重写呢,所以说LinkedHashMap增删改查基本上全是HashMap的逻辑。

(3).改

有几点要注意

1).首先声明一点afterNodeAccess这个方法虽然在HashMap中改变键值对value值的时候都会调用,但是它和改变值没啥关系,真正的改值的逻辑是HashMap中的例如putVal方法,这个方法只是在改完值之后调用一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
        ...
        if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e); //<img draggable="false" role="img" class="emoji" alt="⭐️" src="https://s.w.org/images/core/emoji/15.1.0/svg/2b50.svg"><img draggable="false" role="img" class="emoji" alt="⭐️" src="https://s.w.org/images/core/emoji/15.1.0/svg/2b50.svg"><img draggable="false" role="img" class="emoji" alt="⭐️" src="https://s.w.org/images/core/emoji/15.1.0/svg/2b50.svg"><img draggable="false" role="img" class="emoji" alt="⭐️" src="https://s.w.org/images/core/emoji/15.1.0/svg/2b50.svg">
            return oldValue;
        }
    }
    ++modCount;
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

2).afterNodeAccess的真正作用是把刚刚访问过的节点放到双向链的末尾,一旦执行这个方法那就会打乱我们由插入顺序形成的链表,这个逻辑执不执行由accessOrder变量控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
 * 此方法的作用是将刚刚访问的节点e放到链表的尾端
 */
void afterNodeAccess(Node e) {
    LinkedHashMap.Entry last;
    // accessOrder = true 时 访问节点后才需要置于尾端
    // 如果e本身就在尾端,那就不需要操作
    if (accessOrder && (last = tail) != e) {
        // 记录节点e、e的前驱、e的后继
        LinkedHashMap.Entry p = (LinkedHashMap.Entry)e, b = p.before, a = p.after;
        // 第一步:现将p.after置空
        p.after = null;
        // 第二步:将e的前驱.after 连接上e的后继
        if (b == null)
            // b记录e的前驱,前驱为null,则e在表头,head置为e的后继
            head = a;
        else
            // 否则 e的前驱.after = e的后继
            b.after = a;
        // 第三步:将e的后继.before 连接上e的前驱
        if (a != null)
            // e的后继 != null,将e后继.before = e的前驱
            a.before = b;
        else
            // 否则e的后继 == null,即在e表尾(这里有点多余,前面已经判断在表尾不操作。。。)
            last = b;
        // 第四步:将节点e接入到链表的尾端
        if (last == null)
            // last == null,链表为空,head = p
            head = p;
        else {
            // p.before 指向last(链表尾端),尾端.after = p
            p.before = last;
            last.after = p;
        }
        // 第四步:更新链表新尾端tail
        tail = p;
        // 链表结构性调整,修改次数自增
        ++modCount;
    }
}

注意,到底会不会执行这个方法,是由accessOrder变量控制,而这个变量只有在构造方法中指定才会为ture,其他的构造方法默认都是false不执行这段逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }
    /**
     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
     * with the specified initial capacity and a default load factor (0.75).
     *
     * @param  initialCapacity the initial capacity
     * @throws IllegalArgumentException if the initial capacity is negative
     */
    public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }
    /**
     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
     * with the default initial capacity (16) and load factor (0.75).
     */
    public LinkedHashMap() {
        super();
        accessOrder = false;
    }
    /**
     * Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
     * the same mappings as the specified map.  The <tt>LinkedHashMap</tt>
     * instance is created with a default load factor (0.75) and an initial
     * capacity sufficient to hold the mappings in the specified map.
     *
     * @param  m the map whose mappings are to be placed in this map
     * @throws NullPointerException if the specified map is null
     */
    public LinkedHashMap(Map extends K, ? extends V> m) {
        super();
        accessOrder = false;
        putMapEntries(m, false);
    }
    /**
     * Constructs an empty <tt>LinkedHashMap</tt> instance with the
     * specified initial capacity, load factor and ordering mode.
     *
     * @param  initialCapacity the initial capacity
     * @param  loadFactor      the load factor
     * @param  accessOrder     the ordering mode - <tt>true</tt> for
     *         access-order, <tt>false</tt> for insertion-order
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive
     */
    public LinkedHashMap(int initialCapacity,
                         float loadFactor,
                         boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }

(4).查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public V get(Object key) {
     Node e;
     if ((e = getNode(hash(key), key)) == null)
         return null;
     if (accessOrder)
         afterNodeAccess(e);
     return e.value;
 }
 /**
  * {@inheritDoc}
  */
 public V getOrDefault(Object key, V defaultValue) {
    Node e;
    if ((e = getNode(hash(key), key)) == null)
        return defaultValue;
    if (accessOrder)
        afterNodeAccess(e);
    return e.value;
}

没啥好说的,都是调用的HashMap的代码。

3.遍历

遍历 和hashMap一样,只不过重写了一些方法,重写是为了按插入顺序遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
public Set keySet() {
       Set ks = keySet;
       if (ks == null) {
           ks = new LinkedKeySet();
           keySet = ks;
       }
       return ks;
   }
   final class LinkedKeySet extends AbstractSet {
       public final int size()                 { return size; }
       public final void clear()               { LinkedHashMap.this.clear(); }
       public final Iterator iterator() {
           return new LinkedKeyIterator();
       }
       public final boolean contains(Object o) { return containsKey(o); }
       public final boolean remove(Object key) {
           return removeNode(hash(key), key, null, false, true) != null;
       }
       public final Spliterator spliterator()  {
           return Spliterators.spliterator(this, Spliterator.SIZED |
                                           Spliterator.ORDERED |
                                           Spliterator.DISTINCT);
       }
       public final void forEach(Consumer super K> action) {
           if (action == null)
               throw new NullPointerException();
           int mc = modCount;
           for (LinkedHashMap.Entry e = head; e != null; e = e.after)
               action.accept(e.key);
           if (modCount != mc)
               throw new ConcurrentModificationException();
       }
   }
  public Collection values() {
       Collection vs = values;
       if (vs == null) {
           vs = new LinkedValues();
           values = vs;
       }
       return vs;
   }
   final class LinkedValues extends AbstractCollection {
       public final int size()                 { return size; }
       public final void clear()               { LinkedHashMap.this.clear(); }
       public final Iterator iterator() {
           return new LinkedValueIterator();
       }
       public final boolean contains(Object o) { return containsValue(o); }
       public final Spliterator spliterator() {
           return Spliterators.spliterator(this, Spliterator.SIZED |
                                           Spliterator.ORDERED);
       }
       public final void forEach(Consumer super V> action) {
           if (action == null)
               throw new NullPointerException();
           int mc = modCount;
           for (LinkedHashMap.Entry e = head; e != null; e = e.after)
               action.accept(e.value);
           if (modCount != mc)
               throw new ConcurrentModificationException();
       }
   }
   /**
    * Returns a {@link Set} view of the mappings contained in this map.
    * The set is backed by the map, so changes to the map are
    * reflected in the set, and vice-versa.  If the map is modified
    * while an iteration over the set is in progress (except through
    * the iterator's own <tt>remove</tt> operation, or through the
    * <tt>setValue</tt> operation on a map entry returned by the
    * iterator) the results of the iteration are undefined.  The set
    * supports element removal, which removes the corresponding
    * mapping from the map, via the <tt>Iterator.remove</tt>,
    * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
    * <tt>clear</tt> operations.  It does not support the
    * <tt>add</tt> or <tt>addAll</tt> operations.
    * Its {@link Spliterator} typically provides faster sequential
    * performance but much poorer parallel performance than that of
    * {@code HashMap}.
    *
    * @return a set view of the mappings contained in this map
    */
   public Set<map>> entrySet() {
       Set<map>> es;
       return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
   }
   final class LinkedEntrySet extends AbstractSet<map>> {
       public final int size()                 { return size; }
       public final void clear()               { LinkedHashMap.this.clear(); }
       public final Iterator<map>> iterator() {
           return new LinkedEntryIterator();
       }
       public final boolean contains(Object o) {
           if (!(o instanceof Map.Entry))
               return false;
           Map.Entry,?> e = (Map.Entry,?>) o;
           Object key = e.getKey();
           Node candidate = getNode(hash(key), key);
           return candidate != null && candidate.equals(e);
       }
       public final boolean remove(Object o) {
           if (o instanceof Map.Entry) {
               Map.Entry,?> e = (Map.Entry,?>) o;
               Object key = e.getKey();
               Object value = e.getValue();
               return removeNode(hash(key), key, value, true, true) != null;
           }
           return false;
       }
       public final Spliterator<map>> spliterator() {
           return Spliterators.spliterator(this, Spliterator.SIZED |
                                           Spliterator.ORDERED |
                                           Spliterator.DISTINCT);
       }
       public final void forEach(Consumer super Map.Entry> action) {
           if (action == null)
               throw new NullPointerException();
           int mc = modCount;
           for (LinkedHashMap.Entry e = head; e != null; e = e.after)
               action.accept(e);
           if (modCount != mc)
               throw new ConcurrentModificationException();
       }
   }
   // Map overrides
   public void forEach(BiConsumer super K, ? super V> action) {
       if (action == null)
           throw new NullPointerException();
       int mc = modCount;
       for (LinkedHashMap.Entry e = head; e != null; e = e.after)
           action.accept(e.key, e.value);
       if (modCount != mc)
           throw new ConcurrentModificationException();
   }
   public void replaceAll(BiFunction super K, ? super V, ? extends V> function) {
       if (function == null)
           throw new NullPointerException();
       int mc = modCount;
       for (LinkedHashMap.Entry e = head; e != null; e = e.after)
           e.value = function.apply(e.key, e.value);
       if (modCount != mc)
           throw new ConcurrentModificationException();
   }</map></map></map></map></map>

简单测试一下,是不是按顺序遍历:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class LinkedHashMapTestMain {
    public static void main(String[] args) {
        LinkedHashMap linkedHashMap = new LinkedHashMap();
        for (int i = 0; i > entrySet = linkedHashMap.entrySet();
        Iterator<map>> iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = iterator.next();
            System.out.println("entrySet: " + "key: " + entry.getKey() + "--- value: " + entry.getValue());
        }
        for (Map.Entry entry : entrySet){
            System.out.println("entrySet forEach循环: " + "key: " + entry.getKey() + "--- value: " + entry.getValue());
        }
        //第二种keySet
        Set keySet = linkedHashMap.keySet();
        Iterator keySetIterator = keySet.iterator();
        while (keySetIterator.hasNext()){
            String key = keySetIterator.next();
            System.out.println("keySet: " + "key: " + key + "--- value: " + linkedHashMap.get(key));
        }
        for (String key : keySet){
            System.out.println("keySet forEach循环: " + "key: " + key + "--- value: " + linkedHashMap.get(key));
        }
    }
}</map>

执行结果:

entrySet: key: 0— value: 0
entrySet: key: 1— value: 1
entrySet: key: 2— value: 2
entrySet: key: 3— value: 3
entrySet: key: 4— value: 4
entrySet: key: 5— value: 5
entrySet: key: 6— value: 6
entrySet: key: 7— value: 7
entrySet: key: 8— value: 8
entrySet: key: 9— value: 9
entrySet: key: 10— value: 10
entrySet: key: 11— value: 11
entrySet: key: 12— value: 12
entrySet: key: 13— value: 13
entrySet: key: 14— value: 14
entrySet: key: 15— value: 15
entrySet: key: 16— value: 16
entrySet: key: 17— value: 17
entrySet: key: 18— value: 18
entrySet: key: 19— value: 19
entrySet: key: 20— value: 20
entrySet: key: 21— value: 21
entrySet: key: 22— value: 22
entrySet: key: 23— value: 23
entrySet: key: 24— value: 24
entrySet: key: 25— value: 25
entrySet: key: 26— value: 26
entrySet: key: 27— value: 27
entrySet: key: 28— value: 28
entrySet: key: 29— value: 29
entrySet: key: 30— value: 30
entrySet: key: 31— value: 31
entrySet: key: 32— value: 32
entrySet: key: 33— value: 33
entrySet: key: 34— value: 34
entrySet: key: 35— value: 35
entrySet: key: 36— value: 36
entrySet: key: 37— value: 37
entrySet: key: 38— value: 38
entrySet: key: 39— value: 39
entrySet: key: 40— value: 40
entrySet: key: 41— value: 41
entrySet: key: 42— value: 42
entrySet: key: 43— value: 43
entrySet: key: 44— value: 44
entrySet: key: 45— value: 45
entrySet: key: 46— value: 46
entrySet: key: 47— value: 47
entrySet: key: 48— value: 48
entrySet: key: 49— value: 49
entrySet: key: 50— value: 50
entrySet: key: 51— value: 51
entrySet: key: 52— value: 52
entrySet: key: 53— value: 53
entrySet: key: 54— value: 54
entrySet: key: 55— value: 55
entrySet: key: 56— value: 56
entrySet: key: 57— value: 57
entrySet: key: 58— value: 58
entrySet: key: 59— value: 59
entrySet: key: 60— value: 60
entrySet: key: 61— value: 61
entrySet: key: 62— value: 62
entrySet: key: 63— value: 63
entrySet: key: 64— value: 64
entrySet: key: 65— value: 65
entrySet: key: 66— value: 66
entrySet: key: 67— value: 67
entrySet: key: 68— value: 68
entrySet: key: 69— value: 69
entrySet: key: 70— value: 70
entrySet: key: 71— value: 71
entrySet: key: 72— value: 72
entrySet: key: 73— value: 73
entrySet: key: 74— value: 74
entrySet: key: 75— value: 75
entrySet: key: 76— value: 76
entrySet: key: 77— value: 77
entrySet: key: 78— value: 78
entrySet: key: 79— value: 79
entrySet: key: 80— value: 80
entrySet: key: 81— value: 81
entrySet: key: 82— value: 82
entrySet: key: 83— value: 83
entrySet: key: 84— value: 84
entrySet: key: 85— value: 85
entrySet: key: 86— value: 86
entrySet: key: 87— value: 87
entrySet: key: 88— value: 88
entrySet: key: 89— value: 89
entrySet: key: 90— value: 90
entrySet: key: 91— value: 91
entrySet: key: 92— value: 92
entrySet: key: 93— value: 93
entrySet: key: 94— value: 94
entrySet: key: 95— value: 95
entrySet: key: 96— value: 96
entrySet: key: 97— value: 97
entrySet: key: 98— value: 98
entrySet: key: 99— value: 99
entrySet forEach循环: key: 0— value: 0
entrySet forEach循环: key: 1— value: 1
entrySet forEach循环: key: 2— value: 2
entrySet forEach循环: key: 3— value: 3
entrySet forEach循环: key: 4— value: 4
entrySet forEach循环: key: 5— value: 5
entrySet forEach循环: key: 6— value: 6
entrySet forEach循环: key: 7— value: 7
entrySet forEach循环: key: 8— value: 8
entrySet forEach循环: key: 9— value: 9
entrySet forEach循环: key: 10— value: 10
entrySet forEach循环: key: 11— value: 11
entrySet forEach循环: key: 12— value: 12
entrySet forEach循环: key: 13— value: 13
entrySet forEach循环: key: 14— value: 14
entrySet forEach循环: key: 15— value: 15
entrySet forEach循环: key: 16— value: 16
entrySet forEach循环: key: 17— value: 17
entrySet forEach循环: key: 18— value: 18
entrySet forEach循环: key: 19— value: 19
entrySet forEach循环: key: 20— value: 20
entrySet forEach循环: key: 21— value: 21
entrySet forEach循环: key: 22— value: 22
entrySet forEach循环: key: 23— value: 23
entrySet forEach循环: key: 24— value: 24
entrySet forEach循环: key: 25— value: 25
entrySet forEach循环: key: 26— value: 26
entrySet forEach循环: key: 27— value: 27
entrySet forEach循环: key: 28— value: 28
entrySet forEach循环: key: 29— value: 29
entrySet forEach循环: key: 30— value: 30
entrySet forEach循环: key: 31— value: 31
entrySet forEach循环: key: 32— value: 32
entrySet forEach循环: key: 33— value: 33
entrySet forEach循环: key: 34— value: 34
entrySet forEach循环: key: 35— value: 35
entrySet forEach循环: key: 36— value: 36
entrySet forEach循环: key: 37— value: 37
entrySet forEach循环: key: 38— value: 38
entrySet forEach循环: key: 39— value: 39
entrySet forEach循环: key: 40— value: 40
entrySet forEach循环: key: 41— value: 41
entrySet forEach循环: key: 42— value: 42
entrySet forEach循环: key: 43— value: 43
entrySet forEach循环: key: 44— value: 44
entrySet forEach循环: key: 45— value: 45
entrySet forEach循环: key: 46— value: 46
entrySet forEach循环: key: 47— value: 47
entrySet forEach循环: key: 48— value: 48
entrySet forEach循环: key: 49— value: 49
entrySet forEach循环: key: 50— value: 50
entrySet forEach循环: key: 51— value: 51
entrySet forEach循环: key: 52— value: 52
entrySet forEach循环: key: 53— value: 53
entrySet forEach循环: key: 54— value: 54
entrySet forEach循环: key: 55— value: 55
entrySet forEach循环: key: 56— value: 56
entrySet forEach循环: key: 57— value: 57
entrySet forEach循环: key: 58— value: 58
entrySet forEach循环: key: 59— value: 59
entrySet forEach循环: key: 60— value: 60
entrySet forEach循环: key: 61— value: 61
entrySet forEach循环: key: 62— value: 62
entrySet forEach循环: key: 63— value: 63
entrySet forEach循环: key: 64— value: 64
entrySet forEach循环: key: 65— value: 65
entrySet forEach循环: key: 66— value: 66
entrySet forEach循环: key: 67— value: 67
entrySet forEach循环: key: 68— value: 68
entrySet forEach循环: key: 69— value: 69
entrySet forEach循环: key: 70— value: 70
entrySet forEach循环: key: 71— value: 71
entrySet forEach循环: key: 72— value: 72
entrySet forEach循环: key: 73— value: 73
entrySet forEach循环: key: 74— value: 74
entrySet forEach循环: key: 75— value: 75
entrySet forEach循环: key: 76— value: 76
entrySet forEach循环: key: 77— value: 77
entrySet forEach循环: key: 78— value: 78
entrySet forEach循环: key: 79— value: 79
entrySet forEach循环: key: 80— value: 80
entrySet forEach循环: key: 81— value: 81
entrySet forEach循环: key: 82— value: 82
entrySet forEach循环: key: 83— value: 83
entrySet forEach循环: key: 84— value: 84
entrySet forEach循环: key: 85— value: 85
entrySet forEach循环: key: 86— value: 86
entrySet forEach循环: key: 87— value: 87
entrySet forEach循环: key: 88— value: 88
entrySet forEach循环: key: 89— value: 89
entrySet forEach循环: key: 90— value: 90
entrySet forEach循环: key: 91— value: 91
entrySet forEach循环: key: 92— value: 92
entrySet forEach循环: key: 93— value: 93
entrySet forEach循环: key: 94— value: 94
entrySet forEach循环: key: 95— value: 95
entrySet forEach循环: key: 96— value: 96
entrySet forEach循环: key: 97— value: 97
entrySet forEach循环: key: 98— value: 98
entrySet forEach循环: key: 99— value: 99
keySet: key: 0— value: 0
keySet: key: 1— value: 1
keySet: key: 2— value: 2
keySet: key: 3— value: 3
keySet: key: 4— value: 4
keySet: key: 5— value: 5
keySet: key: 6— value: 6
keySet: key: 7— value: 7
keySet: key: 8— value: 8
keySet: key: 9— value: 9
keySet: key: 10— value: 10
keySet: key: 11— value: 11
keySet: key: 12— value: 12
keySet: key: 13— value: 13
keySet: key: 14— value: 14
keySet: key: 15— value: 15
keySet: key: 16— value: 16
keySet: key: 17— value: 17
keySet: key: 18— value: 18
keySet: key: 19— value: 19
keySet: key: 20— value: 20
keySet: key: 21— value: 21
keySet: key: 22— value: 22
keySet: key: 23— value: 23
keySet: key: 24— value: 24
keySet: key: 25— value: 25
keySet: key: 26— value: 26
keySet: key: 27— value: 27
keySet: key: 28— value: 28
keySet: key: 29— value: 29
keySet: key: 30— value: 30
keySet: key: 31— value: 31
keySet: key: 32— value: 32
keySet: key: 33— value: 33
keySet: key: 34— value: 34
keySet: key: 35— value: 35
keySet: key: 36— value: 36
keySet: key: 37— value: 37
keySet: key: 38— value: 38
keySet: key: 39— value: 39
keySet: key: 40— value: 40
keySet: key: 41— value: 41
keySet: key: 42— value: 42
keySet: key: 43— value: 43
keySet: key: 44— value: 44
keySet: key: 45— value: 45
keySet: key: 46— value: 46
keySet: key: 47— value: 47
keySet: key: 48— value: 48
keySet: key: 49— value: 49
keySet: key: 50— value: 50
keySet: key: 51— value: 51
keySet: key: 52— value: 52
keySet: key: 53— value: 53
keySet: key: 54— value: 54
keySet: key: 55— value: 55
keySet: key: 56— value: 56
keySet: key: 57— value: 57
keySet: key: 58— value: 58
keySet: key: 59— value: 59
keySet: key: 60— value: 60
keySet: key: 61— value: 61
keySet: key: 62— value: 62
keySet: key: 63— value: 63
keySet: key: 64— value: 64
keySet: key: 65— value: 65
keySet: key: 66— value: 66
keySet: key: 67— value: 67
keySet: key: 68— value: 68
keySet: key: 69— value: 69
keySet: key: 70— value: 70
keySet: key: 71— value: 71
keySet: key: 72— value: 72
keySet: key: 73— value: 73
keySet: key: 74— value: 74
keySet: key: 75— value: 75
keySet: key: 76— value: 76
keySet: key: 77— value: 77
keySet: key: 78— value: 78
keySet: key: 79— value: 79
keySet: key: 80— value: 80
keySet: key: 81— value: 81
keySet: key: 82— value: 82
keySet: key: 83— value: 83
keySet: key: 84— value: 84
keySet: key: 85— value: 85
keySet: key: 86— value: 86
keySet: key: 87— value: 87
keySet: key: 88— value: 88
keySet: key: 89— value: 89
keySet: key: 90— value: 90
keySet: key: 91— value: 91
keySet: key: 92— value: 92
keySet: key: 93— value: 93
keySet: key: 94— value: 94
keySet: key: 95— value: 95
keySet: key: 96— value: 96
keySet: key: 97— value: 97
keySet: key: 98— value: 98
keySet: key: 99— value: 99
keySet forEach循环: key: 0— value: 0
keySet forEach循环: key: 1— value: 1
keySet forEach循环: key: 2— value: 2
keySet forEach循环: key: 3— value: 3
keySet forEach循环: key: 4— value: 4
keySet forEach循环: key: 5— value: 5
keySet forEach循环: key: 6— value: 6
keySet forEach循环: key: 7— value: 7
keySet forEach循环: key: 8— value: 8
keySet forEach循环: key: 9— value: 9
keySet forEach循环: key: 10— value: 10
keySet forEach循环: key: 11— value: 11
keySet forEach循环: key: 12— value: 12
keySet forEach循环: key: 13— value: 13
keySet forEach循环: key: 14— value: 14
keySet forEach循环: key: 15— value: 15
keySet forEach循环: key: 16— value: 16
keySet forEach循环: key: 17— value: 17
keySet forEach循环: key: 18— value: 18
keySet forEach循环: key: 19— value: 19
keySet forEach循环: key: 20— value: 20
keySet forEach循环: key: 21— value: 21
keySet forEach循环: key: 22— value: 22
keySet forEach循环: key: 23— value: 23
keySet forEach循环: key: 24— value: 24
keySet forEach循环: key: 25— value: 25
keySet forEach循环: key: 26— value: 26
keySet forEach循环: key: 27— value: 27
keySet forEach循环: key: 28— value: 28
keySet forEach循环: key: 29— value: 29
keySet forEach循环: key: 30— value: 30
keySet forEach循环: key: 31— value: 31
keySet forEach循环: key: 32— value: 32
keySet forEach循环: key: 33— value: 33
keySet forEach循环: key: 34— value: 34
keySet forEach循环: key: 35— value: 35
keySet forEach循环: key: 36— value: 36
keySet forEach循环: key: 37— value: 37
keySet forEach循环: key: 38— value: 38
keySet forEach循环: key: 39— value: 39
keySet forEach循环: key: 40— value: 40
keySet forEach循环: key: 41— value: 41
keySet forEach循环: key: 42— value: 42
keySet forEach循环: key: 43— value: 43
keySet forEach循环: key: 44— value: 44
keySet forEach循环: key: 45— value: 45
keySet forEach循环: key: 46— value: 46
keySet forEach循环: key: 47— value: 47
keySet forEach循环: key: 48— value: 48
keySet forEach循环: key: 49— value: 49
keySet forEach循环: key: 50— value: 50
keySet forEach循环: key: 51— value: 51
keySet forEach循环: key: 52— value: 52
keySet forEach循环: key: 53— value: 53
keySet forEach循环: key: 54— value: 54
keySet forEach循环: key: 55— value: 55
keySet forEach循环: key: 56— value: 56
keySet forEach循环: key: 57— value: 57
keySet forEach循环: key: 58— value: 58
keySet forEach循环: key: 59— value: 59
keySet forEach循环: key: 60— value: 60
keySet forEach循环: key: 61— value: 61
keySet forEach循环: key: 62— value: 62
keySet forEach循环: key: 63— value: 63
keySet forEach循环: key: 64— value: 64
keySet forEach循环: key: 65— value: 65
keySet forEach循环: key: 66— value: 66
keySet forEach循环: key: 67— value: 67
keySet forEach循环: key: 68— value: 68
keySet forEach循环: key: 69— value: 69
keySet forEach循环: key: 70— value: 70
keySet forEach循环: key: 71— value: 71
keySet forEach循环: key: 72— value: 72
keySet forEach循环: key: 73— value: 73
keySet forEach循环: key: 74— value: 74
keySet forEach循环: key: 75— value: 75
keySet forEach循环: key: 76— value: 76
keySet forEach循环: key: 77— value: 77
keySet forEach循环: key: 78— value: 78
keySet forEach循环: key: 79— value: 79
keySet forEach循环: key: 80— value: 80
keySet forEach循环: key: 81— value: 81
keySet forEach循环: key: 82— value: 82
keySet forEach循环: key: 83— value: 83
keySet forEach循环: key: 84— value: 84
keySet forEach循环: key: 85— value: 85
keySet forEach循环: key: 86— value: 86
keySet forEach循环: key: 87— value: 87
keySet forEach循环: key: 88— value: 88
keySet forEach循环: key: 89— value: 89
keySet forEach循环: key: 90— value: 90
keySet forEach循环: key: 91— value: 91
keySet forEach循环: key: 92— value: 92
keySet forEach循环: key: 93— value: 93
keySet forEach循环: key: 94— value: 94
keySet forEach循环: key: 95— value: 95
keySet forEach循环: key: 96— value: 96
keySet forEach循环: key: 97— value: 97
keySet forEach循环: key: 98— value: 98
keySet forEach循环: key: 99— value: 99

到此这篇关于Java LinkedHashMap深入分析源码的文章就介绍到这了,更多相关Java LinkedHashMap内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/code/java/5267.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部