标签:des style io color ar os 使用 for sp
LinkedHashMap
内部采用了散列表和链表实现Map
接口,并可以保证迭代的顺序,和HashMap
不同,其内部维护一个指向所有元素的双向链表,其决定了遍历的顺序,通常是元素插入的顺序进行迭代,不过元素重新插入顺序不会受到影响。
LinkedHashMap
提供一个特殊的构造函数,实现了每次迭代返回最近使用的元素,这个特性可以用于构建LRU缓存。
此外removeEldestEntry(Map.Entry)
方法可以被子类覆盖用于判断在添加元素的时候什么时候可以删除元素。
LinkedHashMap
性能同样受到初始容量和装填因子的影响,对于基本操作(add,contains,remove)在常数时间内,其性能比HashMap
稍微低,由于需要额外代价维护链表;不过其遍历性能为O(size)高于HashMap
O(capacity)。
类定义
直接继承了HashMap
类
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
成员
private transient Entry<K,V> header; //用于遍历的双向链表表头
/**
* The iteration ordering method for this linked hash map:
* true: for access-order, false: for insertion-order
*/
private final boolean accessOrder;
Entry
内部类继承了HashMap.Entry<K,V>
类,增加了两个指针before和after用于维护遍历顺序,实际上Entry
有三个指针父类本身有个next指针用于当发生元素冲突时指向的下一个元素。由此可以看出用于遍历的双向链表直接加在Entry
上面,这样有效节约了空间,实际只比HashMap
多了2*size个引用+1个头结点空间消耗。before和after这两个引用在外部类调用put或remove时,调用其相关方法进行维护(recordAccess和recordRemoval等)。
private static class Entry<K,V> extends HashMap.Entry<K,V> {
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;
}
//existingEntry之前添加当前节点
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
//由父类HashMap的put方法调用,若是acessOrder,则添加到双向链表的头结点后面;本身get方法也会触发调用
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();
}
}
put方法是继承自父类HashMap
,重写了当需要添加元素时候调用的addEntry方法,同样是在对应桶的链表头结点后面添加,添加完以后不是直接进行resize判断,而是判断是否要删除旧的元素,这个方法默认返回false,用户可以重写这个方法用于确定缓存的淘汰机制。
void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);
// Remove eldest entry if instructed, else grow capacity if appropriate
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
} else {
if (size >= threshold)
resize(2 * table.length);
}
}
void createEntry(int hash, K key, V value, int bucketIndex) {
HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<K,V>(hash, key, value, old);
table[bucketIndex] = e;
e.addBefore(header); //每次都是在对应桶链表的开始处添加
size++;
}
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
get方法
public V get(Object key) {
Entry<K,V> e = (Entry<K,V>)getEntry(key);
if (e == null)
return null;
e.recordAccess(this); //实现LRU
return e.value;
}
//重写父类方法,效率更高O(size)
public boolean containsValue(Object value) {
// Overridden to take advantage of faster iterator
if (value==null) {
for (Entry e = header.after; e != header; e = e.after)
if (e.value==null)
return true;
} else {
for (Entry e = header.after; e != header; e = e.after)
if (value.equals(e.value))
return true;
}
return false;
}
LinkedHashMap
同样继承了创建3个集合类视图:键集合、值集合、键值对集合的方法,由于额外维护一个双向链表保证迭代顺序,重写了相关视图的迭代器实现,LinkedHashIterator
通过直接迭代链表的header指针来实现指定顺序遍历。
Iterator<K> newKeyIterator() { return new KeyIterator(); }
Iterator<V> newValueIterator() { return new ValueIterator(); }
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }
private class KeyIterator extends LinkedHashIterator<K> {
public K next() { return nextEntry().getKey(); }
}
private class ValueIterator extends LinkedHashIterator<V> {
public V next() { return nextEntry().value; }
}
private class EntryIterator extends LinkedHashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() { return nextEntry(); }
}
private abstract class LinkedHashIterator<T> implements Iterator<T> {
Entry<K,V> nextEntry = header.after;
Entry<K,V> lastReturned = null;
int expectedModCount = modCount;
public boolean hasNext() {
return nextEntry != header;
}
public void remove() {
if (lastReturned == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
LinkedHashMap.this.remove(lastReturned.key);
lastReturned = null;
expectedModCount = modCount;
}
Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (nextEntry == header)
throw new NoSuchElementException();
Entry<K,V> e = lastReturned = nextEntry;
nextEntry = e.after;
return e;
}
}
LinkedHashMap
继承自HashMap
,相关基本操作性能略低于HashMap
,由于需要额外代价维护链表。其遍历操作是通过操作该双向链表实现,而非内部散列表数组,因此性能为O(size)比HashMap
O(capacity)更高。LinkedHashMap
并没有重新创建一个新的链表来实现顺序遍历,而是在每个Entry上多加了两个指针来决定遍历顺序,有效节约了空间消耗。实际只比HashMap
多了2*size个引用+1个头结点空间消耗。LinkedHashMap
支持元素淘汰策略,可以通过重写removeEldestEntry
方法,来决定调用put时候是否需要删除旧的元素。LinkedHashMap
可以用于实现LRU缓存,并自定义元素淘汰策略。标签:des style io color ar os 使用 for sp
原文地址:http://blog.csdn.net/changer328/article/details/40866167