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

__EOF__

本文作者飞飞很要强
本文链接https://www.cnblogs.com/LiPengFeiii/p/15762301.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   飞飞很要强  阅读(122)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示