美文网首页
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