美文网首页
<> linkedhashmap如何保证有序

<> linkedhashmap如何保证有序

作者: monk87 | 来源:发表于2019-06-03 21:16 被阅读0次

LinkedHashMap这个基础类,默认支持按照插入的书序去访问.这个是怎么做到的 ?
其实很简单 ,就是这个类内部维护了一个双向链表.有了这个双向链表,往前往后都很好控制顺序.

//看一个测试代码
LinkedHashMap<String, String> s = new LinkedHashMap<>();
        //
        s.put("a", "1");
        s.put("b", "2");
        s.put("c", "3");
        //
        Iterator<Map.Entry<String, String>> iterator = s.entrySet().iterator();
        //输出了顺序 a,b,c
        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            System.out.println("kv: " + next.getKey() + " : " + next.getValue());
        }

这个是怎么实现的 ? 首先他继承 HashMap, hashmap再put的时候,linkedhashmap重写了构建node部分

//新建一个node
 Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }
//构建自身的链表
// link at the end of list
    private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }

完成了这个 之后,在访问的时候就可以使用这个链表了 .请看下面分析

首先自己实现了 LinkedEntrySetLinkedHashIterator

  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();
        }
    }
 final class LinkedEntryIterator extends LinkedHashIterator
        implements Iterator<Map.Entry<K,V>> {
        public final Map.Entry<K,V> next() { return nextNode(); }
    }

可以看到调用的时候根据entryset拿到iterator之后 返回的是自己类的iteraotr,重写了 next()函数,直接调用
nextNode(). 请看下nextndoe

 final LinkedHashMap.Entry<K,V> nextNode() {
            LinkedHashMap.Entry<K,V> e = next;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            current = e;
            next = e.after;
            return e;
        }

可以看到 .其实就是再访问自己构建的这个链表

相关文章

网友评论

      本文标题:<> linkedhashmap如何保证有序

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