一、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;