美文网首页
LinkedHashMap

LinkedHashMap

作者: 手打丸子 | 来源:发表于2019-01-27 19:14 被阅读0次

    本文环境为JDK8

    LinkedHashMap的目的是有序的map,遍历顺序与塞入顺序相同

    我们跟着源代码来看看LinkedHashMap的内部结构

    首先是构造器,是HashMap的一个子类,基本数据结构、方法与HashMap相同

    public class LinkedHashMap<K,V>
        extends HashMap<K,V>
        implements Map<K,V>
    

    在HashMap的基础上,增加了两个LinkedHashMap.Entry的变量,用来记录一个LinkedList的头和尾,而这个LinkedList就是用来有序的记录各个LinkedHashMap.Entry的

    /**
         * The head (eldest) of the doubly linked list.
         */
        transient LinkedHashMap.Entry<K,V> head;
    
        /**
         * The tail (youngest) of the doubly linked list.
         */
        transient LinkedHashMap.Entry<K,V> tail;
    

    我们来看一下put方法,put方法使用的依旧是HashMap的put方法,在put中调用了afterNodeAccess(e),这个方法HashMap本身是空函数,而LinkedHashMap有实现

    afterNodeAccess将插入的节点移动到LinkedList的尾部;put的时候有可能是新增,有可能是修改值,无论新增还是修改,都会移动到尾部

    void afterNodeAccess(Node<K,V> e) { // move node to last
            LinkedHashMap.Entry<K,V> last;
            if (accessOrder && (last = tail) != e) {
                LinkedHashMap.Entry<K,V> p =
                    (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
                p.after = null;
                if (b == null)
                    head = a;
                else
                    b.after = a;
                if (a != null)
                    a.before = b;
                else
                    last = b;
                if (last == null)
                    head = p;
                else {
                    p.before = last;
                    last.after = p;
                }
                tail = p;
                ++modCount;
            }
        }
    

    然后我们来看看遍历的时候用的entrySet方法,从head节点开始一个个遍历:

    public Set<Map.Entry<K,V>> entrySet() {
            Set<Map.Entry<K,V>> es;
            return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
        }
    
    final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
            public final int size()                 { return size; }
            public final void clear()               { LinkedHashMap.this.clear(); }
            public final Iterator<Map.Entry<K,V>> 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<K,V> 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.Entry<K,V>> spliterator() {
                return Spliterators.spliterator(this, Spliterator.SIZED |
                                                Spliterator.ORDERED |
                                                Spliterator.DISTINCT);
            }
            public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
                if (action == null)
                    throw new NullPointerException();
                int mc = modCount;
                for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after)
                    action.accept(e);
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    

    相关文章

      网友评论

          本文标题:LinkedHashMap

          本文链接:https://www.haomeiwen.com/subject/ezvwjqtx.html