了解 LinkedHashMap

本文共2618字,阅读本文大概需要5~9分钟

原理

  • LinkedHashMap,会记录你插入的 key-value 的顺序,如果你遍历的时候,它是按照插入的 key-value 对的顺序遍历出来的
  • LinkedHashMap 是 HashMap 的一个子类,与 TreeMap 的区别是,他们都可以维持 key 的顺序,只是 LinkedHashMap 底层是基于链表来实现的,TreeMap 是基于红黑树来实现顺序的
  • LinkedHashMap 其实原则上来说一些基本的原理和操作跟 HashMap是差不多的,唯一主要的区别就是在插入、覆盖、删除的时候,它会记录一下 key-value 对的顺序,用一个链表来记录,在遍历的时候,就可以按照这个顺序来遍历了

基本操作

public static void main(String[] args) {
    Map<Integer, String> map = new LinkedHashMap<>();
    map.put(2,"张三");
    map.put(1,"李四");
    map.put(3,"王五");
    map.remove(2);
    map.put(1,"ls");
    for(Map.Entry<Integer, String> entry : map.entrySet()){
        System.out.println(entry.getKey()+"--->"+entry.getValue());
    }
}

#######################
输出:
1--->ls
3--->王五

Map的遍历

  • 方法一
for(Map.Entry<Integer, String> entry : map.entrySet()){
   System.out.println(entry.getKey()+"--->"+entry.getValue());
}
  • 方法二
Iterator it = map.entrySet().iterator();
while(it.hasNext()){
    Map.Entry<Integer, String> entry = (Map.Entry<Integer, String>) it.next();
    System.out.println(entry.getKey()+"=="+entry.getValue());
}
  • 方法三
Iterator<Integer> its = map.keySet().iterator();
while (its.hasNext()) {
    Integer key = its.next();
    System.out.println(key + "==" + map.get(key));
}
  • 方法四
Set set = map.entrySet();
Iterator i = set.iterator();
while(i.hasNext()){
    Map.Entry<Integer, String> entry1=(Map.Entry<Integer, String>)i.next();
    System.out.println(entry1.getKey()+"=="+entry1.getValue());
}

put()方法

在调用LinkedHashMap的 put() 方法的时候,一定会调用到 HashMap的 put() 方法里面去,调用完 put() 方法,插入一个 key-value 对之后,其实就会调用 afterNodeInsertion(evict) 这个方法去回调 LinkedHashMap 里面子类的实现

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

调用下面这个方法,其实它就是实现了 LinkedHashMap 的逻辑,用来记录插入 key-value 对的顺序,用一个链表来记录

Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
    // 将节点封装为了一个LinkedHashMap.Entry对象
    LinkedHashMap.Entry<K,V> p =
        new LinkedHashMap.Entry<K,V>(hash, key, value, e);
    // 使用linkNodeLast(p)这个东西,将这个节点挂到一个链表里去
    linkNodeLast(p);
    return p;
}



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

关于值的覆盖

如果我们要做对 key 值的覆盖,可以看到,你多次覆盖一个值,不会改变它的顺序,LinkedHashMap 有一个参数,你可以在构造的时候传入进去,accessOrder,这个值默认为 false,如果是默认为 false 的话,那么当你 get 一个key,或者是覆盖这个key的值,都不会改变它在链表里的顺序
但是如果 accessOrder 是 true 的话,那么当你get一个key,或者覆盖这个key的值,就会导致这个 key-value 对顺序会在链表里改变,他会被挪动到链表的尾部去,如果你把accessOrder 指定为true,你每次修改一个key的值或者是get一个这个key,都会导致这个key挪动到尾部去
你删除某个元素的时候,就会将那个元素从链表中摘除
在迭代的时候,LinkedHashMap里面会从链表的头部开始迭代,这样通过这个链表就可以维持他的一个顺序

posted @   小羊abc  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示