关于WeakhashMap与HashMap之间的区别和联系
作者:强钦钦
Java中四大引用:(强>软>弱>虚)
- 强引用
//A a是创建一个引用,new A()是开辟一块地址空间存放引用的对象 , A a = new A(); //a是强引用,只要是强引用,GC(即垃圾回收)就不会回收被引用的对象(即new A())
- 软引用SoftReference
一般用于实现Java对象的缓存,缓存可有 可无,一般将有用但是非必须的对象用 软引用关联,只要是软引用关联的对象,在Java发生 内存溢出 异常之前,会将这些对象列入要 回收的范围(即内存不够才回收),如果回收之后发现内存还是不够,才会抛出OOM异常,用软引用关联起来,使用时直接get,就不用每次创建 。例如 假设map频繁被使用 -》可用 SoftReference关联 -》 用 SoftReference.get()获取该对象,以便调用其方法
- 弱引用 WeakReference
弱引用是用来一些非必须的对象,比软引用更弱一些,只要是被弱引用关联的对象,只能够生存到下一次垃圾回收之前,一旦发生垃圾回收,无论当前内存是否够用,都会回收掉被弱引用关联的对象
- 虚引用 PhantomReference
别名幽灵引用 最弱的引用关系,一个对象是否具有虚引用的存在,完全是不会对其生命周期产生影响,也无法通过虚引用获取一个对象的实例,它存在的唯一目的就是在对象被垃圾回收之后收到一个系统通知
特殊的HashMap:WeakHashMap
键是弱引用对象,只能存活到下一次垃圾回收之前;
被回收的键放在 ReferenceQueue里,在HashMap里,会 根据ReferenceQueue里的值,把键对应的value找到,然后把结点移除,同时让当前的value不要引用原先的对象,这些对象才能在下一次垃圾回收时再被回收掉
代码测试
package collection;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.WeakHashMap;
class MyArray{
byte[] bytes = new byte[3*1024*1024]; //即占用3M
}
class Test{
}
public class TestReference {
public static void main(String[] args) {
// //引用队列
// //将软引用对象关联成一个key值,添加到队列里,遍历 队列中每个元素分别找到其在 HashMap里的位置,然后把结点(key,value)完全删除掉
// ReferenceQueue<MyArray> queue = new ReferenceQueue<>();
// //创建一个软引用对象
// SoftReference<MyArray> softReference = new SoftReference<>(new MyArray(), queue);//当对象被回收时,会直接入到queue里
// //获取软引用对象(softReference)
// System.out.println(softReference.get());
// //判断是否被回收(true 被回收 入到队列)
// System.out.println(softReference.isEnqueued());
// // -Xms3M -Xmx5M 即初始给堆3M空间,最大是5M空间 右键-》 run configurations——》设置虚拟机参数
// //System.gc();//可模拟垃圾回收
// byte[] array = new byte[3*1024*1024];
//
// System.out.println(softReference.get());
// System.out.println(softReference.isEnqueued());
// // 弱引用对象
// ReferenceQueue<Test> queue = new ReferenceQueue<>();
// WeakReference<Test> weakReference = new WeakReference<>(new Test(), queue);
//
// System.out.println(weakReference.get());
// System.out.println(weakReference.isEnqueued());
//
// System.gc();
//
// System.out.println(weakReference.get());
// System.out.println(weakReference.isEnqueued());
//
// //虚引用对象
// ReferenceQueue<Test> queue = new ReferenceQueue<>();
// PhantomReference<Test> phantomReference = new PhantomReference<>(new Test(), queue);
// //进程的执行,需要线程的支持
// //垃圾回收作为一个线程(等CPU分配时间片)支持虚拟机的执行
// //JDK(或虚拟机)里垃圾回收线程是随机启动的,调用 System.gc();可以手动回收
// System.gc();
// if(phantomReference.isEnqueued()){
// System.out.println("该对象已经被回收");
// }else{
// System.out.println("该对象已经被回收");
// }
}
}类的继承关系
HashMap中的对象可以被拷贝 克隆 序列到磁盘上,WeakhashMap都不行
重要方法
- WeakhashMap的put方法(key重复,新值覆盖旧值;头插新节点)
- hash算法不一样(WeakhashMap源码297行 )
/**
* Retrieve object hash code and applies a supplemental hash function to the
* result hash, which defends against poor quality hash functions. This is
* critical because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits.
*/
final int hash(Object k) {
int h = k.hashCode();
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}//HashMap337行
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}- put(447行)不能放键为NULL,系统会自动new一个 NULLKEY,HashMap的key和value都可以为null;
- WeakhashMap中的put/get/remove/resize等方法均会使用expungeStaleEntries()方法,用来遍历ReferenceQueue找到里面的key所对应的结点清除掉
使用场景
- WeakHashMap的键是弱引用关联对象;
- HashMap是强引用关联
到此这篇关于关于WeakhashMap与HashMap之间的区别和联系的文章就介绍到这了,更多相关WeakhashMap与HashMap内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
