摘要
WeakHashMap
类和HashMap
原理相似,HashMap
之前已经做过详细的记录,现在我们主要介绍WeakHashMap
和HashMap
相比有哪些异同以及在用法上有什么区别。
实现原理对比
最主要的区别
源码
话不多说,直接上源码:
/**
* The entries in this hash table extend WeakReference, using its main ref
* field as the key.
*/
private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
V value;
final int hash;
Entry<K,V> next;
/**
* Creates new entry.
*/
Entry(Object key, V value,
ReferenceQueue<Object> queue,
int hash, Entry<K,V> next) {
super(key, queue);
this.value = value;
this.hash = hash;
this.next = next;
}
@SuppressWarnings("unchecked")
public K getKey() {
return (K) WeakHashMap.unmaskNull(get());
}
public V getValue() {
return value;
}
public V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
K k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
V v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return false;
}
public int hashCode() {
K k = getKey();
V v = getValue();
return Objects.hashCode(k) ^ Objects.hashCode(v);
}
public String toString() {
return getKey() + "=" + getValue();
}
}
这个Entry
内部类是最主要的区别:它实现了WeakReference
接口
java虚拟机&内存回收
我们知道,在编码习惯上,Java相对于C,C++的一个重要的区别是:java在编码过程中不需要手动释放内存空间,也就是说,java程序员只需要new....new......new即可,内存满了有jvm进行垃圾清理,而C,C++并非如此,需要程序员手动的进行变量的申请和释放,否则不用的变量就会一直存在,造成内存泄漏。
jvm的内存回收机制有很多种,我们这里仅大概介绍其工作方式:
首先,jvm分为新生代和老年代,新生代是指近期new出来的空间,还未经过垃圾回收。老年代是已经经过一次甚至多次垃圾回收后仍然“挺下来”的变量,一般为常量、全局变量或者编程人员定义的常用变量等等。
jvm在合适的时候,会自动出发垃圾回收,jvm辨别申请的变量是否还有用的标准是程序中是否有此地址的有效引用,即此变量是否可达。而在判断是否可达时,标准就是强引用。
WeakReference
WeakReference
,直白的翻译过来就是弱引用.jvm在判断某一个变量是否可达时,不会看这个变量的弱引用。也就是说,WeakReference
定义的变量,即便你程序中有明确的指向,jvm也不care,该回收就回收。
其他区别
- 采用和java7相同的哈希数组+拉链法进行数据存储,不进行拉链、红黑树转换。这点和java8的
HashMap
不同【我猜是每触发一次GC,此类就被清光光了,没必要做那么多的性能优化】 - 哈希地址的计算和java7一样【估计是java8没有专门对他优化】
-
transfer
和java7一样是头插,会逆序 - 在发现元素过少后,会有类似缩容的操作
综上。。。。。我觉得,java8就没动它,jdk8中的WeakHashMap
估计就是从jdk7中直接搬过来了。
类用途及注意事项
用途
WeakHashMap
和HashMap
很像:都是用哈希计算进行数据存储,存储效率都比较高,用来存储数据很棒。
WeakHashMap
由于编程者无法对Map
中元素回收进行干预,经常会出现前一秒不为空,后一面变成空了这样的现象。但是从另一个方面来说,WeakHashMap
能够保持Map
中的元素一直是最新的,自动清除旧元素,而且不会很大,查找方便。这种特性决定了它用来做缓存还是很棒的。
注意事项
缓存,知道原理后别发懵就行。
网友评论