记:
今天面试有两道印象比较深刻的题目。Java语言的。
关于LinkedHashMap类的实现
LinkedHashMap类
@API
LinkedHashMap类
public class LinkedHashMap
/**
* The head of the doubly linked list.
*/
private transient Entry<K,V> header;
下面是关于Entry的创建
private static class Entry<K,V> extends HashMap.Entry<K,V> {
// These fields comprise the doubly linked list used for
// iteration.
//类的entry里面增加了双向链表需要用到的墙后两个fields成员变量
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;
}
/**
* 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.
*/
//这里只重写了HashMap的recordAccess方法来实现链表的维护
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();
}
}
在LinkedHashMap的初始化之处,初始化了链表
/**
* Called by superclass constructors and pseudoconstructors (clone,
* readObject) before any entries are inserted into the map.
* Initializes the chain.
*/
@Override
void init() {
header = new Entry<>(-1, null, null, null);
header.before = header.after = header;
}
经过上面的代码,我们可以看到LinkedHashMap对链表的基本实现过程。
LinkedHashMap特性
就是实现了链表方法
优势在于使用双向链表来会维护Map的key-value对的插入顺序。key-value对就是Entry了。
LinkedHashMap可以避免对HashMap里的key-value对进行排序(只要插入key-value对时保持顺序就可以了),同时又可以避免使用TreeMap所增加的成本。
但是,由于LinkedHashMap需要维护元素的插入顺序,因此性能略低于HashMap的性能;再但是,因为它以链表来维护,所以在迭代访问Map里的全部元素时候有较好的性能。
下面是LinkedHashMap的迭代器实现代码
private abstract class LinkedHashIterator<T> implements Iterator<T> {
Entry<K,V> nextEntry = header.after;
Entry<K,V> lastReturned = null;
/**
* The modCount value that the iterator believes that the
* backing List should have. If this expectation is
* violated, the iterator has detected concurrent
* modification.
*/
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的了解大概到这里。有机会再深入补充。