- Lru的意思是先淘汰时间最远的哪一个,LFU则淘汰使用频率最小的哪一个。
- Hashmap
static int indexFor(int h, int length) {
return h & (length-1);
}
相当于%但length要是2的幂。
hashCode()
用来确定对象在hashmap
中的位置,函数返回一个整数,如果a.equals(b)
则a.hashCode()==b.hashCode()
这两个函数一个用来确定对象是否相等,一个在hashMap
中区分元素。hashCode()
和equals()
的默认实现相似是内存地址。
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
这个table[0]位置不光存了key==null的值,别的key也可能hash到这个位置
void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
src[j] = null;
do {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}
}
- 重新计算每个元素在表中的位置因为hash()%length中的length发生了变化并不是只要将table[i]中的一串列表直接移到newTable[i]中就行了。
- table[i]中是单链表以null结尾
final Entry<K,V> removeMapping(Object o) {
if (!(o instanceof Map.Entry))
return null;
Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
Object key = entry.getKey();
int hash = (key == null) ? 0 : hash(key.hashCode());
int i = indexFor(hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> e = prev;
// 删除链表中的“键值对e”
// 本质是“删除单向链表中的节点”
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && e.equals(entry)) {
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
}
return e;
}
这个函数要是在双链表的实现中就可以直接删除了不用再找了。
- 快速失败 fast-fail防止别的线程改变了表的结构
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException();
// 注意!!!
// 一个Entry就是一个单向链表
// 若该Entry的下一个节点不为空,就将next指向下一个节点;
// 否则,将next指向下一个链表(也是下一个Entry)的不为null的节点。
if ((next = e.next) == null) {
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;
return e;
}
始终保持next为下一个,那么获取下一个就是返回next,next跟新为next的下一个。hasNext()就是检测next是否为null这种设计主要是为了hasNext();
- 迭代器定义在
hashMap
内部他的构造函数为private所以只能有hashMap
调用,迭代器由于是hashMap
的内部类,可以之间操纵hashMap
的内部结构,而next()方法由于生命为public
可以被外部调用。
3、HashMap共有四个构造方法。构造方法中提到了两个很重要的参数:初始容量和加载因子。这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中槽的数量(即哈希数组的长度),初始容量是创建哈希表时的容量(从构造函数中可以看出,如果不指明,则默认为16),加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 resize 操作(即扩容)。
文/Maat红飞(简书作者)
原文链接:http://www.jianshu.com/p/fc9e37ee2afd
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
4、HashMap中key和value都允许为null。
扩容是一个相当耗时的操作,因为它需要重新计算这些元素在新的数组中的位置并进行复制处理。因此,我们在用HashMap的时,最好能提前预估下HashMap中元素的个数,这样有助于提高HashMap的性能。
如果hashmap
中有重复key则第二次插入讲第一次的value覆盖