MST

星途 面试题库

面试题:Java中LinkedHashMap双向链表的结构及特点

请阐述Java中LinkedHashMap的双向链表结构是如何组织的,以及这种结构相比普通HashMap有哪些显著特点。
15.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

LinkedHashMap双向链表结构组织方式

  1. 节点定义
    • LinkedHashMap的节点类Entry继承自HashMap的Node类,在Node基础上新增了两个字段:Entry<K,V> beforeEntry<K,V> after,用于维护双向链表关系。
    • 例如:
    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }
    
  2. 链表维护
    • LinkedHashMap有两个特殊的节点,headtail,分别指向双向链表的头和尾。
    • 当向LinkedHashMap中插入新元素时,新元素会被添加到双向链表的尾部(默认情况下,可通过构造函数改变这种行为)。例如,执行put(K key, V value)操作时,新创建的Entry节点会被添加到链表尾部,并且在put过程中会通过修改beforeafter指针来维护链表的双向性。
    • 当删除元素时,会调整双向链表中相关节点的beforeafter指针,使链表保持连续。例如,执行remove(Object key)操作时,找到要删除的Entry节点后,会将其前驱节点的after指针指向其后继节点,后继节点的before指针指向其前驱节点。

相比普通HashMap的显著特点

  1. 顺序性
    • LinkedHashMap可以维护插入顺序或者访问顺序。
    • 插入顺序:元素按照插入到LinkedHashMap中的顺序排列。例如,依次插入元素A、B、C,那么遍历LinkedHashMap时,顺序就是A、B、C。
    • 访问顺序:当设置accessOrdertrue时,每次访问(getput已存在的键值对)一个元素,该元素会被移到双向链表的尾部。这使得最近访问的元素总是在链表尾部,而最久未访问的元素在链表头部,常用于实现LRU(最近最少使用)缓存。
  2. 遍历性能
    • 由于LinkedHashMap维护了双向链表结构,在遍历元素时,时间复杂度为O(n),其中n为元素个数。相比之下,普通HashMap在遍历其元素时,由于其内部基于哈希表存储,遍历顺序是不确定的,且可能由于哈希冲突等原因,遍历性能在某些情况下不如LinkedHashMap(特别是需要按照特定顺序遍历的场景)。
  3. 迭代器稳定性
    • LinkedHashMap的迭代器在迭代过程中具有更好的稳定性。在迭代过程中,如果不删除当前迭代的元素,不会影响迭代的顺序。而普通HashMap在迭代过程中,如果发生结构修改(如添加或删除元素),可能会抛出ConcurrentModificationException,且其迭代顺序不确定。