美文网首页
思考LinkedHashMap

思考LinkedHashMap

作者: enjoycc97 | 来源:发表于2018-07-28 19:02 被阅读0次

学习有序HashMap实现原理

挖掘背后实现,加深对java集合框架理解

demo书写

这时候打印的就是put时候的顺序,但是换成HashMap就是乱序的

LinkedHashMap<String,String> map=new LinkedHashMap();
        map.put("a","1");
        map.put("b","2");
        map.put("c","3");
        Iterator<Map.Entry<String,String>> iterator=map.entrySet().iterator();
        while(iterator.hasNext()){
            Log.d("TEST",iterator.next().getKey());
        }

分析put操作

发现LinkedHashMap本身没有写put逻辑,也就是直接用父类方法,HashMap的put方法。是不是很疑惑?
后来找了发现是因为

Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMapEntry<K,V> p =
            new LinkedHashMapEntry<K,V>(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }
private void linkNodeLast(LinkedHashMapEntry<K,V> p) {
        LinkedHashMapEntry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }

原来真正的原理是在这里,所以分析一下数据结构

static class LinkedHashMapEntry<K,V> extends HashMap.Node<K,V> {
        LinkedHashMapEntry<K,V> before, after;
        LinkedHashMapEntry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

这里和HashMap的结构几乎一样,但是多了2个指向前后的指针。
在插入节点的时候,根据linkNodeLast的方法分析,会将插入的节点成员变量before
赋值为当前last也就是tail,指向尾节点。也就是说每一次put的时候,把put对象的before设置成当前尾节点。把当前尾节点after设置成put对象。以后一个个加进来,顺序也就找到了。
感觉这里用到比较多的是链表,看这个源码最好对链表比较好的掌握,后面也分析比较方便一点

再看遍历逻辑:
迭代器学习
由于每一个Map都会用Set<Node>存储节点数据结构,所以我们这里找一下linkedHashMap内部节点数据结构是什么

 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();
        }

所以如果想看迭代怎么依次找出顺序的节点就应该找 LinkedEntryIterator

 final class LinkedEntryIterator extends LinkedHashIterator
        implements Iterator<Map.Entry<K,V>> {
        public final Map.Entry<K,V> next() { return nextNode(); }
    }
final LinkedHashMapEntry<K,V> nextNode() {
            LinkedHashMapEntry<K,V> e = next;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            current = e;
            next = e.after;
            return e;
        }

哈哈哈,这里看出来就是一个个找到 LinkedHashMapEntry.after
所以迭代器就是迭代LinkedHashMapEntry成员变量after,至于after是什么时候赋值的。也就是put的时候。原来有序map是这么实现的啊,是不是很简单。

相关文章

网友评论

      本文标题:思考LinkedHashMap

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