首页 > 其他分享 >LinkedHashMap

LinkedHashMap

时间:2024-07-13 23:20:25浏览次数:12  
标签:顺序 last key Entry null LinkedHashMap

  • HashMap 是无序的,LinkedHashMap 是可以维持插入顺序的
  • LinkedHashMap 继承了 HashMap,内部追加了双向链表,来维护元素的插入顺序
// LinkedHashMap.Entry 继承了 HashMap.Node
static class Entry<K,V> extends HashMap.Node<K,V> {
    // 并追加了连个字段 before 和 after,用来维持键值对的关系。
    Entry<K,V> before, after;
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

插入顺序

  • LinkedHashMap 并未重写 HashMap 的 put() 方法,而是重写了 put() 方法需要调用的内部方法 newNode()
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;
}
  • 在 LinkedHashMap 中,链表中的节点顺序是按照插入顺序维护的。当使用 put() 方法向 LinkedHashMap 中添加键值对时,会将新节点插入到链表的尾部,并更新 before 和 after 属性,以保证链表的顺序关系
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;
    }
}

访问顺序

  • 要维护访问顺序,需要我们在声明 LinkedHashMap 的时候指定三个参数
// 第三个参数如果为 true 的话,就表示 LinkedHashMap 要维护访问顺序
LinkedHashMap<String, String> map = new LinkedHashMap<>(16, .75f, true);
  • get()后会调用afterNodeAcess()
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;
}
// true 表示访问顺序,false 表示插入顺序
final boolean accessOrder;

// 把刚访问的节点移动到链表的尾部
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;
    }
}
  • LinkedHashMap的put调用的是父类HashMap的put方法,HashMap的put方法会调用putVal方法,其中会调用afterNodeAccess和afterNodeInsertion
// 在插入节点后,如果需要,可能会删除最早加入的元素
// evict 是否需要删除最早加入的元素
void afterNodeInsertion(boolean evict) { // possibly remove eldest
    LinkedHashMap.Entry<K,V> first;
    // removeEldestEntry() 方法会判断第一个元素是否超出了可容纳的最大范围,如果超出,那就会调用 removeNode() 方法对最不经常访问的那个元素进行删除。
    if (evict && (first = head) != null && removeEldestEntry(first)) {
        K key = first.key;
        removeNode(hash(key), key, null, false, true);
    }
}
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;
}
  • LinkedHashMap 继承自 HashMap,它在 HashMap 的基础上,增加了一个双向链表来维护键值对的顺序。这个链表可以按照插入顺序或访问顺序排序,它的头节点表示最早插入或访问的元素,尾节点表示最晚插入或访问的元素。这个链表的作用就是让 LinkedHashMap 可以保持键值对的顺序,并且可以按照顺序遍历键值对。

  • LinkedHashMap 还提供了两个构造方法来指定排序方式,分别是按照插入顺序排序和按照访问顺序排序。在按照访问顺序排序的情况下,每次访问一个键值对,都会将该键值对移到链表的尾部,以保证最近访问的元素在最后面。如果需要删除最早加入的元素,可以通过重写 removeEldestEntry() 方法来实现。

标签:顺序,last,key,Entry,null,LinkedHashMap
From: https://www.cnblogs.com/sprinining/p/18300963

相关文章

  • 在Java中,Map 接口的实现(如 HashMap,LinkedHashMap,TreeMap 等)并不保证遍历 keySet() 或
    在Java中,Map接口的实现(如HashMap,LinkedHashMap,TreeMap等)并不保证遍历keySet()或entrySet()时的顺序。但是,某些特定的Map实现确实提供了特定的遍历顺序。1、HashMap:它基于哈希表实现,并不保证映射的顺序,特别是遍历顺序。因此,当你使用map.keySet()遍历HashMap时,结果可......
  • LinkedHashMap排序
    importjava.util.LinkedHashMap;importjava.util.Map;importjava.util.TreeMap; publicclassSortLinkedHashMapByKey{publicstaticvoidmain(String[]args){//创建一个LinkedHashMapLinkedHashMap<Integer,String>linkedHashMap=newLinkedHashMap<......
  • 利用LinkedHashMap实现简单的LRU
    利用LinkedHashMap进行重写,实现LRU作为缓存字典1、代码实现importjava.util.LinkedHashMap;importjava.util.Map;/***利用LinkedHashMap进行重写,实现LRU作为缓存字典**@param<K>key*@param<V>value*@date2024-04-1009:42**/publicclassLRUCach......
  • 接口测试-json文件读取报java.lang.ClassCastException: java.util.LinkedHashMap can
    问题原因:从json文件中读取的信息为hashMap,与预期(类对象)格式不匹配,无法解析。问题分析:json文件包含一个json串列表,代表向接口中传递不同的参数组合,通过下面方法读取json文件信息,反序列化成类对象,并把这些赋值的对象进行接口请求参数进行传递。publicList<T>getReadValuesLi......
  • 【揭秘】如何使用LinkedHashMap来实现一个LUR缓存?
    LRU(LeastRecentlyUsed)缓存是一种常用的缓存淘汰策略,用于在有限的缓存空间中存储数据。其基本思想是:如果数据最近被访问过,那么在未来它被访问的概率也更高。因此,LRU缓存会保留最近访问过的数据,并在缓存满时淘汰最久未使用的数据定义LRU(LeastRecentlyUsed)缓存是一种常用的......
  • LinkedHashMap
    概述Hashtableandlinkedlistimplementationofthe<tt>Map</tt>interface,withpredictableiterationorder.Thisimplementationdiffersfrom<tt>HashMap</tt>inthatitmaintainsadoubly-linkedlistrunningthroughallofitsen......
  • HashMap、LinkedHashMap和TreeMap:你真的了解它们吗?
    亲爱的小伙伴们,大家好呀!我是小米,一个热衷于技术分享的90后程序员。今天我要和大家聊聊一个在面试中经常会被问到的话题:HashMap、LinkedHashMap、TreeMap的区别。这可是一个非常重要的知识点,不仅在面试中会被频繁提及,而且在实际开发中也经常用到。让我们一起深入了解这三者的异同吧!H......
  • 有序map linkedhashmap
    linkedHashMap中的元素会按照put()进去的顺序进行排序第一个put进去的元素就会放在第一位,以此类推原因是因为:linkedhashmap中维护的是数组与双向链表,第一个值会指向第二个值,第二个又指向第三个,所以就有序了linkedhashmap中有一个特点,可以删除不经常访问(get(key)方法)的元素,不经长......
  • java list转linkedHashMap
    JavaList转LinkedHashMap在Java编程中,我们经常会遇到需要将一个List转换为LinkedHashMap的场景。List是一个有序的集合,而LinkedHashMap是一个有序的键值对集合,它可以保持插入顺序。这种转换可以帮助我们在处理数据时更方便地按照特定的顺序进行操作。使用Java的StreamAPI进行Li......
  • HashMap 、LinkedHashMap 、 Hashtable 、ConcurrentHashMap的使用区别和Collections
    LinkedHashMapLinkedHashMap的使用publicstaticvoidmain(String[]args){ LinkedHashMap<String,Integer>map=newLinkedHashMap<>(); //添加元素 Integerput1=map.put("大文",25); Integerput2=map.put("小文",26); Integer......