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; }
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; } }