#HashMap与LinkedHashMap的区别 ##LinkedHashMap类代码 public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> 从类的声明来看LinkedHashMap继承自HashMap。那么两者有什么区别呢?
-
linkedHashMap是有序的。
-
private transient Entry<K,V> header; 这个是整个链表的头。
void init() { header = new Entry<>(-1, null, null, null); header.before = header.after = header; } 在初始化时候对双向链表进行维护。
//这个entity就是每个key-value对应的实体类, 因为继承自HashMap.Entity,所以自带HashMap.Entity的next,get等属性 private static class Entry<K,V> extends HashMap.Entry<K,V> { // These fields comprise the doubly linked list used for iteration. Entry<K,V> before, after;
Entry(int hash, K key, V value, HashMap.Entry<K,V> next) { super(hash, key, value, next); } //删除当前节点, 将当前链表的收尾重新拼接 private void remove() { before.after = after; after.before = before; } /** * Inserts this entry before the specified existing entry in the list. */ private void addBefore(Entry<K,V> existingEntry) { after = existingEntry; before = existingEntry.before; before.after = this; after.before = this; } /** * This method is invoked by the superclass whenever the value * of a pre-existing entry is read by Map.get or modified by Map.set. * If the enclosing Map is access-ordered, it moves the entry * to the end of the list; otherwise, it does nothing. */ void recordAccess(HashMap<K,V> m) { LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m; if (lm.accessOrder) { lm.modCount++; remove(); addBefore(lm.header); } } void recordRemoval(HashMap<K,V> m) { remove(); }
} 在HashMap.Entity的基础上添加before和after,构成一个双向链表。
-
构造函数不同, 添加了accessOrder 用户选择排序的方式
-
accessOrder the ordering mode - <tt>true</tt> for access-order, <tt>false</tt> for insertion-order
在构造方法中如果设置为true的话, 那么就按照访问的顺序排序(LRU)否则按照插入顺序排序。
##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;
}
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);
}
void createEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}
##LinkedhashMap添加元素代码 因为LinkedHashMap extends HashMap 所以LinkedHashMap拥有HashMap所有方法。LinkedHashMap集合在添加方法时,默认调用父元素的方法, 并维护双向链表。LinkedHashMap 重写了 addEntry和 createEntry。 addEntry 添加了移除最旧使用的条目。 在LRU中用到 createEntry 在原来的方法上添加了对链表的维护
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);
}
}
/**
* This override differs from addEntry in that it doesn't resize the
* table or remove the eldest entry.
*/
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++;
}