zoukankan      html  css  js  c++  java
  • LinkedHashMap源码

    TreeMap是一颗红黑树做Map。HashMap是数组+链表+红黑树。HashTable是数组+链表。

    LinkedHashMap底层存储结构与HashMap一样,不同的是LinkedHashMap增加了一个双向链表的头节点,插入的数据除了插入HashMap,还会插入链表中,因而可以保存插入节点的顺序

    LinkedHashMap的节点在HashMap节点的基础上增加了前后节点的引用

    LinkedHashMap相比HashMap在查找值和删除值时效率要高

    LinkedHashMap还可以设置按插入顺序排序或是按访问顺序排序,默认是按插入顺序排序

    LinkedHashMap没有put方法,而是覆写了afterNodeAccess方法和afterNodeInsertion方法。当插入的数据已经存在时,会调用afterNodeAccess方法看是否需要将数据插入到链表末尾;当插入的数据是新数据时,会通过afterNodeInsertion方法来根据设置删除近期使用最少的节点

    LinkedHashMap可以用来实现LRU算法。首先需要用可以设置accessOrder的构造函数设置accessOrder为true,也就是按照节点访问顺序排序;

    LinkedHashMap还拥有HashMap一样的结构,原因在于其继承自HashMap,因此HashMap中用于存储元素的table也被继承过来,于是乎元素的存储也具备和HashMap一样的规则,所有元素存储在table中,table下的每个索引在原HashMap的结构下也是一个单向链表,同时每个元素中额外增加的before和after引用将table中的元素互连起来。

    HashMap链表节点:next

    HashMap红黑树节点TreeNodeparentleftrightprevnext 

    LinkedHashMap链表节点:beforeafternext 

    LinkedHashMapHashMap一样,只不过增加了headtail把所有元素串联起来了。

    public class testLinkedHashMap1 {
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public static void main(String[] args) {
            LinkedHashMap1<Integer,String> hh = new LinkedHashMap1<Integer,String>();
            
            //链表添加
            hh.put(0, "0");//放到LinkedHashMap1的table[0]中,此时是链表(节点有next没有after,before)
            hh.put(16, "16");
    //        hh.remove(4);//链表删除
    //        hh.put(4, "4");
            hh.put(32, "32");
            hh.put(48, "48");//0位置转成红黑树
            hh.put(54, "54");
            hh.put(60, "60");
            hh.put(76, "76");
            hh.put(1, "1");//1位置链表添加
            hh.put(2, "2");
            hh.put(3, "3");
            
            hh.get(1);
            
            Set s = hh.keySet();//[0, 16, 32, 48, 54, 60, 76, 1, 2, 3]
            Iterator i = s.iterator();
            if(i.hasNext()) System.out.println(i.next());
    //        i.remove();
            if(i.hasNext()) System.out.println(i.next());
            
        }
    }
    //extends HashMap1,table也被继承过来,数组+链表+红黑树。
    public class LinkedHashMap1<K, V> extends HashMap1<K, V> implements Map1<K, V> {
        private static final long serialVersionUID = 3801124242820219131L;
        transient LinkedHashMap1.Entry<K, V> head;// 双向链表的头节点和尾节点
        transient LinkedHashMap1.Entry<K, V> tail;
        final boolean accessOrder;// true,使用节点之后就把节点放到最末尾。false就不放。用于删除第一个最不常用的元素。
    
        private void linkNodeLast(LinkedHashMap1.Entry<K, V> p) {// 链表末尾添加,有before,after
            LinkedHashMap1.Entry<K, V> last = tail;//保留原来的tail
            tail = p;//修改tail
            if (last == null)// tail=null
                head = p;// tail = head = p
            else {
                p.before = last;
                last.after = p;
            }
        }
    
        // dst替换src
        private void transferLinks(LinkedHashMap1.Entry<K, V> src, LinkedHashMap1.Entry<K, V> dst) {
            LinkedHashMap1.Entry<K, V> b = dst.before = src.before;
            LinkedHashMap1.Entry<K, V> a = dst.after = src.after;
            if (b == null)// 替换的src是第一个节点
                head = dst;
            else
                b.after = dst;
            if (a == null)// 替换的src是最后一个节点
                tail = dst;
            else
                a.before = dst;
        }
    
        public void reinitialize() {
            super.reinitialize();// table = null; entrySet = null; keySet = null; values = null;
            head = tail = null;
        }
        //生成一个节点(链表中的节点,不是红黑树中的节点,有hash, key, value, next没有before,after)
        public Node<K, V> newNode(int hash, K key, V value, Node<K, V> e) {// 
            LinkedHashMap1.Entry<K, V> p = new LinkedHashMap1.Entry<K, V>(hash, key, value, e);
            linkNodeLast(p);// 生成新的节点并插入到尾部
            return p;
        }
    
        public Node<K, V> replacementNode(Node<K, V> p, Node<K, V> next) {
            LinkedHashMap1.Entry<K, V> q = (LinkedHashMap1.Entry<K, V>) p;
            LinkedHashMap1.Entry<K, V> t = new LinkedHashMap1.Entry<K, V>(q.hash, q.key, q.value, next);
            transferLinks(q, t);// t替换q
            return t;
        }
    
        public TreeNode<K, V> newTreeNode(int hash, K key, V value, Node<K, V> next) {
            TreeNode<K, V> p = new TreeNode<K, V>(hash, key, value, next);
            linkNodeLast(p);// 末尾添加p
            return p;
        }
    
        public TreeNode<K, V> replacementTreeNode(Node<K, V> p, Node<K, V> next) {
            LinkedHashMap1.Entry<K, V> q = (LinkedHashMap1.Entry<K, V>) p;
            TreeNode<K, V> t = new TreeNode<K, V>(q.hash, q.key, q.value, next);
            transferLinks(q, t);// t替换q
            return t;
        }
    
        public void afterNodeRemoval(Node<K, V> e) { // 删除节点e
            LinkedHashMap1.Entry<K, V> p = (LinkedHashMap1.Entry<K, V>) e, b = p.before, a = p.after;
            p.before = p.after = null;
            if (b == null)
                head = a;
            else
                b.after = a;
            if (a == null)
                tail = b;
            else
                a.before = b;
        }
    
        public void afterNodeInsertion(boolean evict) { // 添加新的节点时候,有可能删除最老的元素
            LinkedHashMap1.Entry<K, V> first;
            if (evict && (first = head) != null && removeEldestEntry(first)) {
                K key = first.key;// 删除第一个元素,每次使用元素之后,就会把元素放到最末尾,第一个元素就是最少使用的元素。
                removeNode(hash(key), key, null, false, true);// hashMap方法,
            }
        }
    
        public void afterNodeAccess(Node<K, V> e) { // 节点e被修改后,e不是尾节点(e是尾节点就不动),把e节点移到最后。
            LinkedHashMap1.Entry<K, V> last;
            if (accessOrder && (last = tail) != e) {
                LinkedHashMap1.Entry<K, V> p = (LinkedHashMap1.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;
            }
        }
    
        public void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
            for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after) {
                s.writeObject(e.key);
                s.writeObject(e.value);
            }
        }
    
        public LinkedHashMap1(int initialCapacity, float loadFactor) {
            super(initialCapacity, loadFactor);// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
            accessOrder = false;// true,使用节点之后就把节点放到最末尾。false就不放。
        }
    
        public LinkedHashMap1(int initialCapacity) {
            super(initialCapacity);// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
            accessOrder = false;
        }
    
        public LinkedHashMap1() {
            super();// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
            accessOrder = false;
        }
    
        public LinkedHashMap1(Map1<? extends K, ? extends V> m) {
            super();// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
            accessOrder = false;
            putMapEntries(m, false);
        }
    
        public LinkedHashMap1(int initialCapacity, float loadFactor, boolean accessOrder) {
            super(initialCapacity, loadFactor);// hashMap方法,构造hashMap的table,一个数组+链表+红黑树
            this.accessOrder = accessOrder;
        }
    
        public boolean containsValue(Object value) {
            for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after) {
                V v = e.value;
                if (v == value || (value != null && value.equals(v)))
                    return true;
            }
            return false;
        }
    
        public V get(Object key) {
            Node<K, V> e;
            if ((e = getNode(hash(key), key)) == null)// hashMap方法
                return null;
            if (accessOrder)
                afterNodeAccess(e);// 把e节点移到最后。
            return e.value;
        }
    
        public V getOrDefault(Object key, V defaultValue) {
            Node<K, V> e;
            if ((e = getNode(hash(key), key)) == null)// hashMap方法
                return defaultValue;
            if (accessOrder)// 把e节点移到最后。
                afterNodeAccess(e);
            return e.value;
        }
    
        public void clear() {
            super.clear();
            head = tail = null;
        }
    
        // 添加一个元素时候是否删除最老的。 map是缓存有用。比如到达100之后,添加一个元素就删除最老的元素。要重写。
        protected boolean removeEldestEntry(Map1.Entry<K, V> eldest) {
            return false;
        }
    
        public Set<K> keySet() {
            Set<K> ks = keySet;
            if (ks == null) {
                ks = new LinkedKeySet();
                keySet = ks;
            }
            return ks;
        }
    
        final class LinkedKeySet extends AbstractSet<K> {
            public final int size() {
                return size;
            }
    
            public final void clear() {
                LinkedHashMap1.this.clear();
            }
    
            public final Iterator<K> 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;// hashMap方法
            }
    
            public final Spliterator<K> 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 (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
                    action.accept(e.key);
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    
        public Collection<V> values() {
            Collection<V> vs = values;
            if (vs == null) {
                vs = new LinkedValues();
                values = vs;
            }
            return vs;
        }
    
        final class LinkedValues extends AbstractCollection<V> {
            public final int size() {
                return size;
            }
    
            public final void clear() {
                LinkedHashMap1.this.clear();
            }
    
            public final Iterator<V> iterator() {
                return new LinkedValueIterator();
            }
    
            public final boolean contains(Object o) {
                return containsValue(o);
            }
    
            public final Spliterator<V> 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 (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
                    action.accept(e.value);
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    
        public Set<Map1.Entry<K, V>> entrySet() {
            Set<Map1.Entry<K, V>> es;
            return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
        }
    
        final class LinkedEntrySet extends AbstractSet<Map1.Entry<K, V>> {
            public final int size() {
                return size;
            }
    
            public final void clear() {
                LinkedHashMap1.this.clear();
            }
    
            public final Iterator<Map1.Entry<K, V>> iterator() {
                return new LinkedEntryIterator();
            }
    
            public final boolean contains(Object o) {
                if (!(o instanceof Map1.Entry))
                    return false;
                Map1.Entry<?, ?> e = (Map1.Entry<?, ?>) o;
                Object key = e.getKey();
                Node<K, V> candidate = getNode(hash(key), key);// hashMap方法
                return candidate != null && candidate.equals(e);
            }
    
            public final boolean remove(Object o) {
                if (o instanceof Map1.Entry) {
                    Map1.Entry<?, ?> e = (Map1.Entry<?, ?>) o;
                    Object key = e.getKey();
                    Object value = e.getValue();
                    return removeNode(hash(key), key, value, true, true) != null;// hashMap方法
                }
                return false;
            }
    
            public final Spliterator<Map1.Entry<K, V>> spliterator() {
                return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT);
            }
    
            public final void forEach(Consumer<? super Map1.Entry<K, V>> action) {
                if (action == null)
                    throw new NullPointerException();
                int mc = modCount;
                for (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
                    action.accept(e);
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }
    
        public void forEach(BiConsumer<? super K, ? super V> action) {
            if (action == null)
                throw new NullPointerException();
            int mc = modCount;
            for (LinkedHashMap1.Entry<K, V> 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 (LinkedHashMap1.Entry<K, V> e = head; e != null; e = e.after)
                e.value = function.apply(e.key, e.value);
            if (modCount != mc)
                throw new ConcurrentModificationException();
        }
    
        public static class Entry<K, V> extends HashMap1.Node<K, V> {
            public Entry<K, V> before, after;// hash, key, value, next
    
            public Entry(int hash, K key, V value, Node<K, V> next) {
                super(hash, key, value, next);// before和after引用节点以支持双向链表
            }
        }
    
        abstract class LinkedHashIterator {//头结点head开始一路after到末尾
            LinkedHashMap1.Entry<K, V> next;
            LinkedHashMap1.Entry<K, V> current;
            int expectedModCount;
    
            LinkedHashIterator() {
                next = head;// 初始化时下一个是head
                expectedModCount = modCount;
                current = null;
            }
    
            public final boolean hasNext() {
                return next != null;
            }
    
            final LinkedHashMap1.Entry<K, V> nextNode() {
                LinkedHashMap1.Entry<K, V> e = next;
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                if (e == null)
                    throw new NoSuchElementException();
                current = e;
                next = e.after;// before和after遍历链表
                return e;
            }
    
            public final void remove() {
                Node<K, V> p = current;
                if (p == null)
                    throw new IllegalStateException();
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                current = null;
                K key = p.key;
                removeNode(hash(key), key, null, false, false);// hashMap方法
                expectedModCount = modCount;
            }
        }
    
        final class LinkedKeyIterator extends LinkedHashIterator implements Iterator<K> {
            public final K next() {
                return nextNode().getKey();
            }
        }
    
        final class LinkedValueIterator extends LinkedHashIterator implements Iterator<V> {
            public final V next() {
                return nextNode().value;
            }
        }
    
        final class LinkedEntryIterator extends LinkedHashIterator implements Iterator<Map1.Entry<K, V>> {
            public final Map1.Entry<K, V> next() {
                return nextNode();
            }
        }
    
    }
  • 相关阅读:
    nginx+upsync+consul 构建动态nginx配置系统
    服务容错保护断路器Hystrix之六:缓存功能的使用
    consul之:ACL配置使用
    Consul之:服务健康监测
    Consul实践指导-DNS接口
    Spring 整合Mybatis实例
    ORACLE SEQUENCE 具体解释
    python高速排序
    降阶法计算行列式方法有个地方有Bug(原文也已更正,此为更正后部分)
    MyBatis在Oracle中插入数据并返回主键的问题解决
  • 原文地址:https://www.cnblogs.com/yaowen/p/11232637.html
Copyright © 2011-2022 走看看