LinkedHashMap
来源:互联网 发布:mac 装了office2016卡 编辑:程序博客网 时间:2024/05/22 16:57
直接先贴代码
import java.util.ConcurrentModificationException;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.NoSuchElementException;public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>{ private static final long serialVersionUID = 3801124242820219131L; // 整个对象就一个头节点,只有前和后节点的引用 private transient Entry<K,V> header; //排序规则 // true 按访问顺序 //false 按照插入顺序 private final boolean accessOrder; //默认都是按照插入顺序,构造函数跟HashMap相同 public LinkedHashMap(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); accessOrder = false; } public LinkedHashMap(int initialCapacity) {super(initialCapacity); accessOrder = false; } public LinkedHashMap() {super(); accessOrder = false; } public LinkedHashMap(Map<? extends K, ? extends V> m) { super(m); accessOrder = false; } //可以执行排位顺序 public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; } //实例化头节点,前后节点都指向自己 void init() { header = new Entry<K,V>(-1, null, null, null); header.before = header.after = header; } //复写了父类的方法,改方法在父类的resize方法中调用,遍历链表,然后将数据插入到Hash槽中,省去了遍历hashMap外层数组麻烦 //本身的链表不需要改变 void transfer(HashMap.Entry[] newTable) { int newCapacity = newTable.length; for (Entry<K,V> e = header.after; e != header; e = e.after) { int index = indexFor(e.hash, newCapacity); e.next = newTable[index]; newTable[index] = e; } } //根据value查询直接遍历链表,比起HashMap的方法简单些 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; } // 复写get方法,添加 e.recordAccess(this);这个操作 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; } public void clear() { super.clear(); header.before = header.after = header; } 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); } /** * Removes this entry from the linked list. */ private void remove() { before.after = after; after.before = before; } private void addBefore(Entry<K,V> existingEntry) { after = existingEntry; before = existingEntry.before; before.after = this; after.before = this; } //排序,如果是false,插入顺序,什么都不做 //如果是true 读取顺序则将改数据移动到链表的末尾 //get和put方法都会调用,put方法在父类中调用的 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(); } } 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;} } 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(); } } // These Overrides alter the behavior of superclass view iterator() methods Iterator<K> newKeyIterator() { return new KeyIterator(); } Iterator<V> newValueIterator() { return new ValueIterator(); } Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); } //覆写HashMap中的addEntry方法,LinkedHashmap并没有覆写HashMap中的put方法, //而是覆写了put方法所调用的addEntry方法和recordAccess方法, //put方法在插入的key已存在的情况下,会调用recordAccess方法, //在插入的key不存在的情况下,要调用addEntry插入新的Entry , //添加新的key也需要添加到链表中 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; //如果有必要,则删除掉该近期最少使用的节点, //这要看对removeEldestEntry的覆写,由于默认为false,因此默认是不做任何处理的。 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++; } //默认返回false,不做处理,如果需要删除需要从写改方法。 protected boolean removeEldestEntry(Map.Entry<K,V> eldest) { return false; }}
1 非线程安全的
2 结构就是HashMap 和LInkedList组合起来,比hashmap多了一个双向链表将表元素串联起来
3 可以实现LRU算法,但是是否删除元素需要重写逻辑才行
4 accessOrder属性 默认为false 插入排序。双向链表不需要做处理,访问排序为true,每次get数据时要将数据移动到双端链表的末尾,put元素肯定是在末尾的
5
0 0
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- LinkedHashMap
- Sql查重、删除多余重复记录
- MySQL里实现类似SPLIT的分割字符串的函数
- 【常用包类】Scanner。
- 线性筛与欧拉函数、莫比乌斯函数
- x86运算指令
- LinkedHashMap
- 高并发解决方案
- 代码赏析:子窗口对于键盘和鼠标的响应
- effective java 读书笔记---第五章 泛型
- java 运算符
- vmstat命令
- Html 第一份作业
- mysql JS 计算两GPS坐标的距离函数:
- jsp页面:改变css样式