集合(五)——LinkedHashMap源码解析以及WeakHashMap、TreeMap的特点

一、LinkedHashMap

1、继承关系:
在这里插入图片描述
在这里插入图片描述
2、基本属性:
HashMap有的它都有,还多了两个:
header:标记指针,用来遍历
accessOrder:顺序性:true:访问有序 false:插入有序 默认:false插入有序

3、构造函数
和HashMap差不多,调用父类构造函数;

4、LinkedHashMap与HashMap不同的点:

  • 继承关系不同:LinkedHashMap继承自HashMap;
  • Entry节点不同:before\after;
  • 新增属性:header、accessOrder; 顺序性:true:访问有序 false:插入有序 默认:false插入有序

5、增删改查方法:
①put方法:

(父类HashMap实现)
public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}
(当前类LinkedHashMap实现)
void addEntry(int hash, K key, V value, int bucketIndex) {
    super.addEntry(hash, key, value, bucketIndex);

    // Remove eldest entry if instructed
    Entry<K,V> eldest = header.after;
    if (removeEldestEntry(eldest)) {
        removeEntryForKey(eldest.key);
    }
}
(父类HashMap实现)
void addEntry(int hash, K key, V value, int bucketIndex) {
    if ((size >= threshold) && (null != table[bucketIndex])) {
        resize(2 * table.length);
        hash = (null != key) ? hash(key) : 0;
        bucketIndex = indexFor(hash, table.length);
    }

    createEntry(hash, key, value, bucketIndex);
}

(当前类LinkedHashMap实现)
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++;
}
(当前类LinkedHashMap实现)
private void addBefore(Entry<K,V> existingEntry) {
    after  = existingEntry;
    before = existingEntry.before;
    before.after = this;
    after.before = this;
}

header属性的初始化在构造函数中完成,创建了一个不存储数据的entry实体:

构造函数调用init():
void init() {
        header = new Entry<>(-1, null, null, null);
        header.before = header.after = header;
    }

②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;
}
final Entry<K,V> getEntry(Object key) {
     if (size == 0) {
         return null;
     }

     int hash = (key == null) ? 0 : hash(key);
     for (Entry<K,V> e = table[indexFor(hash, table.length)];
          e != null;
          e = e.next) {
         Object k;
         if (e.hash == hash &&
             ((k = e.key) == key || (key != null && key.equals(k))))
             return e;
     }
     return null;
}

③remove:
和HashMap实现过程差不多,只不过他还有额外维护一个双向循环链表来保证顺序;

LinkedMap用处在于,在存储数据时,当你想保持进入的顺序与被取出的顺序一致的话,优先考虑LinkedMap;
HashMap使用的是数组+单链表的数据结构(本质上是数组,数组的每个元素是一个单向链表);
LinkedHashMap使用的是HashMap+双向循环链表。

二、WeakHashMap

添加的元素随着时间的推移会减少(弱引用),源码和HashMap的差不多,可以参考HashMap的,只不过它的对象是弱引用的罢了;
继承自AbstractMap;
在这里插入图片描述

三、TreeMap

底层数据结构是红黑树,源码可以参考HashMap的,与HashMap相比,它内部有一个Comparator比较器,所以实现键有序;
继承自AbstractMap;
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值