JDK源码阅读(八) : 增强的HashMap——LinkedHashMap

LinkedHashMap是HashMap的扩展,它内部包含双链表,维持元素的插入顺序或访问顺序。文章详细介绍了其继承关系、节点结构、构造器、查找、添加、修改和删除元素的操作,以及迭代器的实现。LinkedHashMap在多线程环境下需要外部同步,并提供了访问顺序控制,适合作为LRU缓存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 继承关系

LinkedHashMap继承了HashMap类和Map接口。与HashMap的不同之处在于,LinkedHashMap内部保存了一个双链表,这个双链表将所有的key-value对按照加入顺序或者访问顺序连接起来。并且,这个双链表的顺序,也决定了对该LinkedHashMap的迭代顺序。

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>

LinkedHashMap不是线程安全的类,如果需要在多线程环境下使用,应该在外部做好线程同步。

2.成员属性

(1)节点结构

LinkedHashMap的节点类继承了HashMap中的Node类,新增了两个指针,一个指向前驱节点,一个指向后继节点。

static class Entry<K,V> extends HashMap.Node<K,V> {
   
   
  	//前驱指针和后继指针
    Entry<K,V> before, after;
  	//节点的构造器,调用了HashMap.Node类的构造器
    Entry(int hash, K key, V value, Node<K,V> next) {
   
   
        super(hash, key, value, next);
    }
}

(2)双链表的头指针

transient LinkedHashMap.Entry<K,V> head;

(3)双链表的尾指针

transient LinkedHashMap.Entry<K,V> tail;

(4)accessOrder

如果accessOrder为true,则把访问过的元素放在链表后面,放置顺序是访问的顺序。此时,最近最少访问(least-recently)的元素会置于链表前面,最近访问较多(most-recently)的元素会置于链表后面。这也使得LinkedHashMap非常适用于建立LRU缓存

如果accessOrder为false,则按插入顺序来遍历。

final boolean accessOrder;

3. 构造器

(1)空参构造器,使用了默认的初始容量16和装载因子0.75。accessOrder设置为false,表示遍历顺序为元素插入的顺序。

public LinkedHashMap() {
   
   
    super();
    accessOrder = false;
}

(2)设置初始容量的构造器,装载因子默认0.75,accessOrder设置为false。

public LinkedHashMap(int initialCapacity) {
   
   
    super(initialCapacity);
    accessOrder = false;
}

(3)设置初始容量和装载因子的构造器,accessOrder设置为false。

public LinkedHashMap(int initialCapacity, float loadFactor) {
   
   
    super(initialCapacity, loadFactor);
    accessOrder = false;
}

(4)传入一个map的构造器,将该map中所有的元素都加入到新创建的map中,accessOrder设置为false。

public LinkedHashMap(Map<? extends K, ? extends V> m) {
   
   
  	//先建一个空的map
    super();
    accessOrder = false;
  	//再把参数map中的所有元素都加入到新map中,该方法是HashMap中的方法
    putMapEntries(m, false);
}

当调用putMapEntries方法将参数容器m中所有的元素添加到本容器中时,使用了foreach循环,来获取m中的所有键值对。而foreach循环是基于while循环和迭代器的,所以应该按照m所遵循的迭代规则,依次取得元素,放入本容器中。

final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
   
   
    int s = m.size();
    if (s > 0) {
   
   
        if (table == null) {
   
    // pre-size
            float ft = ((float)s / loadFactor) + 1.0F;
            int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                     (int)ft : MAXIMUM_CAPACITY);
            if (t > threshold)
                threshold = tableSizeFor(t);
        }
        else if (s > threshold)
            resize();
      	//使用了foreach循环
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
   
   
            K key = e.getKey();
            V value = e.getValue();
          	//放置节点时,会按照插入顺序,进行链表连接,在第5节进行具体说明
            putVal(hash(key), key, value, false, evict)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值