LinkedHashMap

LinkedHashMap

说明:HashMap可以保存 k=v 的结构,但不保证迭代器的顺序
为了提供有顺序的hashmap,jdk提供此类
默认使用的插入的顺序
可以通过构造器设置为按照访问顺序

继承关系

  • 继承HashMap ,因此已经具备所有Map功能,只需要自定义需要的特殊功能

构造器

  • LinkedHashMap(int, float) 设定初始大小和负载因子

  • LinkedHashMap(int) 设定初始大小.负载因子默认(0.75)

  • LinkedHashMap() 初始大小使用16(使用父类HashMap设定)

  • LinkedHashMap(Map<? extends K, ? extends V>) 使用默认构造器,并将指定map中数据初始化保存到此map中

  • [特殊]LinkedHashMap(int, float, boolean) 设置顺序为读/写?

    默认设置,顺序使用写入顺序,使用此构造器new LinkedHashMap(16,0.75,true) 可设置为按照访问的顺序
    

field

  • transient LinkedHashMap.Entry<K,V> head; 第一个节点
  • transient LinkedHashMap.Entry<K,V> tail; 最后一个节点
  • accessOrder : boolean 插入/访问顺序

方法

containsValue(Object) 检测指定值是否在map中

 // linkedHashmap 重写了此方法,但没有重写 containsKey
 // 因为key有hash优化,而value没有,只能迭代检查. 
 // hashmap 中node 要双循环, 这里则是单循环,所有做了重写
	public boolean containsValue(Object value) {
        for (LinkedHashMap.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;
    }

    
    
    // hashmap.containsValue
         Node<K,V>[] tab; V v;
        if ((tab = table) != null && size > 0) {
            for (Node<K,V> e : tab) {
                for (; e != null; e = e.next) {
                    if ((v = e.value) == value ||
                        (value != null && value.equals(v)))
                        return true;
                }
            }
        }
        return false;

get

// 需要在获取到key之后,根据设置,移动节点位置到最后(如果设置为访问顺序) 
public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }

afterNodeAccess

// 访问之后.将被访问节点放到最后
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;
        }
    }

afterNodeInsertion(boolean)

// put之后将node节点放到最后
    void afterNodeInsertion(boolean evict) { // possibly remove eldest
        LinkedHashMap.Entry<K,V> first;
        if (evict && (first = head) != null && removeEldestEntry(first)) {
            K key = first.key;
            removeNode(hash(key), key, null, false, true);
        }
    }  

afterNodeRemoval

void afterNodeRemoval(Node<K,V> e) { // unlink
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.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;
    }

newNode(int, K, V, Node<K, V>)

LinkedHashMap 没有在put方法中处理tail问题,
而是把tail问题放在了newNode中 
也就是map中如果要放入新的节点,必然要创建新的node,只要把新建的node作为tail就能保证tail问题

newTreeNode(int, K, V, Node<K, V>)

处理 treeNode 情况    同理: replacementNode  replacementTreeNode方法

迭代器 LinkedHashIterator

// 从head 开始迭代,以next为标志abstract class LinkedHashIterator {        LinkedHashMap.Entry<K,V> next;        LinkedHashMap.Entry<K,V> current;        int expectedModCount;        LinkedHashIterator() {            next = head;            expectedModCount = modCount;            current = null;        }        public final boolean hasNext() {            return next != null;        }        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;        }        public final void remove() {            Node<K,V> p = current;            if (p == null)                throw new IllegalStateException();            if (modCount != expectedModCount)                throw new ConcurrentModificationException();            current = null;            removeNode(p.hash, p.key, null, false, false);            expectedModCount = modCount;        }    }
posted @ 2022-01-04 14:23  飞飞很要强  阅读(111)  评论(0编辑  收藏  举报