
LinkedHashMap是Map具有可预知的迭代顺序的实现,支持所有的可选操作。
Key和Value可以是任意值,包括null。
所有的条目都保存在双链表中。默认的迭代顺序是将键插入到Map中的顺序。重复插入一个已存在的键值不会改变插入顺序。如果使用了三个参数的构造函数,并且accessOrder指定为true,则迭代顺序为条目被访问的顺序。访问顺序受到put,get,和putAll操作的影响,但不受collection 视图操作的影响。
注意:LinkedHashMap的实现不是同步的。如果多个线程同时访问Map,而其中至少一个线程从结构上修改了Map,则LinkedHashMap必须保持同步。对于迭代顺序为插入顺序的Map实例,结构修改是指移除或添加一个条目的操作。对于迭代顺序为访问顺序的Map实例,结构修改是指put,get和putAll这些方法对条目顺序的改变。对于条目中Value的改变不算是结构修改。
假如Map正在改变结构,与此同时,迭代器正好迭代过这些元素,那么,迭代器就有可能抛出ConcurrentModificationException。只有迭代器提供的remove方法允许在迭代过程中移除元素。但不能保证这种机制能够在异步并发修改中起作用。这只能使用在调试情况下。
LinkedHashMap继承自HashMap,内部自己维护了一个运行于所有条目的双向链表。
1、类结构
public class LinkedHashMap<K, V> extends HashMap<K, V> implements Map<K, V>
2、重要的成员变量
/**
* The head of the doubly linked list.
*/
private transient Entry<K, V> header;
/**
* The iteration ordering method for this linked hash map: <tt>true</tt>
* for access-order, <tt>false</tt> for insertion-order.
*
* @serial
*/
private final boolean accessOrder;
其中Entry类是LinkedHashMap的内部定义,代码片段如下:
//继承了HashMap.Entry
private static class Entry<K, V> extends HashMap.Entry<K, V>
//新增的两个成员变量
Entry<K, V> before, after;
3、重要的方法
/**
* This override alters behavior of superclass put method. It causes newly
* allocated entry to get inserted at the end of the linked list and
* removes the eldest entry if appropriate.
*/
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);
}
}
/**
* 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<K,V>(hash, key, value, old);
table[bucketIndex] = e;
e.addBefore(header);
size++;
}
protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
return false;
}
4、基本LinkedHashMap的实现
public static class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
/** serialVersionUID */
private static final long serialVersionUID = -5933045562735378538L;
/** 最大数据存储容量 */
private static final int LRU_MAX_CAPACITY = 1024;
/** 存储数据容量 */
private int capacity;
/**
* 默认构造方法
*/
public LRULinkedHashMap() {
super();
}
/**
* 带参数构造方法
* @param initialCapacity 容量
* @param loadFactor 装载因子
* @param isLRU 是否使用LRU算法,true:使用(按方案顺序排序);false:不使用(按存储顺序排序)
*/
public LRULinkedHashMap(int initialCapacity, float loadFactor, boolean isLRU) {
super(initialCapacity, loadFactor, true);
capacity = LRU_MAX_CAPACITY;
}
/**
* 带参数构造方法
* @param initialCapacity 容量
* @param loadFactor 装载因子
* @param isLRU 是否使用LRU算法,true:使用(按方案顺序排序);false:不使用(按存储顺序排序)
* @param lruCapacity lru存储数据容量
*/
public LRULinkedHashMap(int initialCapacity, float loadFactor, boolean isLRU, int lruCapacity) {
super(initialCapacity, loadFactor, true);
this.capacity = lruCapacity;
}
/**
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
@Override
protected boolean removeEldestEntry(Entry<K, V> eldest) {
System.out.println(eldest.getKey() + "=" + eldest.getValue());
if(size() > capacity) {
return true;
}
return false;
}
}
本文深入探讨了LinkedHashMap的内部结构、关键成员变量与方法,特别关注其如何通过双向链表实现预知迭代顺序,并解释了LRU缓存策略的实现方式。通过实例分析,揭示了如何利用LinkedHashMap进行高效的数据存储与访问。
1443

被折叠的 条评论
为什么被折叠?



