浅谈 Java 集合框架 - 来看看 LinkHashMap 是啥?

发布于 2023-07-23 22:25:07 字数 2472 浏览 30 评论 0

跳槽后,就没怎么看 jdk,趁着十一看回点集合框架。我们知道 HashMap 是无序的,jdk 也给我们提供了算是有序的 HashMap,即 LinkedHashMap。然而它只保留了操作的相对有序,而非 TreeMap 的 Key 自然有序。


LinkedHashMap 显然继承了 HashMap 的绝大部分特性,新 Entry 则添加了 before 和 after 两个指针,以及维护 Entry 链表的方法。需要说明的是,HashMap.Entry 的单链表无关,那只是用于解决 hash 冲突而已。

/**
 * LinkedHashMap entry.
 */
private static class Entry<K,V> extends HashMap.Entry<K,V> {
  //提供了双链表的指针
  Entry<K,V> before, after;

  Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
    super(hash, key, value, next);
  }

  //删除元素,改变头尾指针
  private void remove() {
      before.after = after;
      after.before = before;
  }

  //链表头追加元素
  private void addBefore(Entry<K,V> existingEntry) {
      after  = existingEntry;
      before = existingEntry.before;
      before.after = this;
      after.before = this;
  }

  /**
   * 记录访问,即使将最新一次访问放在链表头部
   */
  void recordAccess(HashMap<K,V> m) {
      LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
      //构造方法能够设置该值
      if (lm.accessOrder) {
          lm.modCount++;
          remove();
          addBefore(lm.header);
      }
  }

  void recordRemoval(HashMap<K,V> m) {
      remove();
  }
}

//重写了get方法
public V get(Object key) {
  Entry<K,V> e = (Entry<K,V>)getEntry(key);
  if (e == null)
      return null;
  //访问记录
  e.recordAccess(this);
  return e.value;
}

void addEntry(int hash, K key, V value, int bucketIndex) {
  super.addEntry(hash, key, value, bucketIndex);

  //移除最近且使用次数最少的元素
  Entry<K,V> eldest = header.after;
  if (removeEldestEntry(eldest)) {
      removeEntryForKey(eldest.key);
  }
}

//多了将Entry添加到双链表头
void createEntry(int hash, K key, V value, int bucketIndex) {
  HashMap.Entry<K,V> old = table[bucketIndex];
  Entry<K,V> e = new Entry<>(hash, key, value, old);
  table[bucketIndex] = e;
  //在此
  e.addBefore(header);
  size++;
}

//重写该方法,可以实现lru,可以参考ehcache的SpoolingLinkedHashMap
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
  return false;
}

//判断value是否存在显然方便好多,直接遍历双链表
public boolean containsValue(Object value) {
  if (value==null) {
      for (Entry e = header.after; e != header; e = e.after)
          if (e.value==null)
              return true;
  } else {
      for (Entry e = header.after; e != header; e = e.after)
          if (value.equals(e.value))
              return true;
  }
  return false;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

风情万种。

暂无简介

文章
评论
28 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文