(特别篇)java集合(四)Map集合之WeakHashMap详解之弱引用详解

本篇文章尝试从What、Why、How这三个角度来探索Java中的弱引用,理解Java中弱引用的定义、基本使用场景和使用方法。由于个人水平有限,叙述中难免存在不准确或是不清晰的地方,希望大家可以指出,谢谢大家:)

1. What——什么是弱引用?**

Java中的弱引用具体指的是java.lang.ref.WeakReference<T>类,我们首先来看一下官方文档对它做的说明:

弱引用对象的存在不会阻止它所指向的对象变被垃圾回收器回收。弱引用最常见的用途是实现规范映射(canonicalizing mappings,比如哈希表)。

假设垃圾收集器在某个时间点决定一个对象是弱可达的(weakly reachable)(也就是说当前指向它的全都是弱引用),这时垃圾收集器会清除所有指向该对象的弱引用,然后垃圾收集器会把这个弱可达对象标记为可终结(finalizable)的,这样它们随后就会被回收。与此同时或稍后,垃圾收集器会把那些刚清除的弱引用放入创建弱引用对象时所登记到的引用队列(Reference Queue)中。

实际上,Java中存在四种引用,它们由强到弱依次是:强引用、软引用、弱引用、虚引用。下面我们简单介绍下除弱引用外的其他三种引用:

  • 强引用(Strong Reference):通常我们通过new来创建一个新对象时返回的引用就是一个强引用,若一个对象通过一系列强引用可到达,它就是强可达的(strongly reachable),那么它就不被回收
  • 软引用(Soft Reference):软引用和弱引用的区别在于,若一个对象是弱引用可达,无论当前内存是否充足它都会被回收,而软引用可达的对象在内存不充足时才会被回收,因此软引用要比弱引用“强”一些
  • 虚引用(Phantom Reference):虚引用是Java中最弱的引用,那么它弱到什么程度呢?它是如此脆弱以至于我们通过虚引用甚至无法获取到被引用的对象,虚引用存在的唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被销毁。

2. Why——为什么使用弱引用?

考虑下面的场景:现在有一个Product类代表一种产品,这个类被设计为不可扩展的,而此时我们想要为每个产品增加一个编号。一种解决方案是使用HashMap<Product, Integer>。于是问题来了,如果我们已经不再需要一个Product对象存在于内存中(比如已经卖出了这件产品),假设指向它的引用为productA,我们这时会给productA赋值为null,然而这时productA过去指向的Product对象并不会被回收,因为它显然还被HashMap引用着。所以这种情况下,我们想要真正的回收一个Product对象,仅仅把它的强引用赋值为null是不够的,还要把相应的条目从HashMap中移除。显然“从HashMap中移除不再需要的条目”这个工作我们不想自己完成,我们希望告诉垃圾收集器:在只有HashMap中的key在引用着Product对象的情况下,就可以回收相应Product对象了。显然,根据前面弱引用的定义,使用弱引用能帮助我们达成这个目的。我们只需要用一个指向Product对象的弱引用对象来作为HashMap中的key就可以了。

3. How——如何使用弱引用?

拿上面介绍的场景举例,我们使用一个指向Product对象的弱引用对象来作为HashMap的key,只需这样定义这个弱引用对象:

productA = new Product(...);
WeakReference<Product> weakProductA = new WeakReference<>(productA);

现在,若引用对象weakProductA就指向了Product对象productA。那么我们怎么通过weakProduct获取它所指向的Product对象productA呢?很简单,只需要下面这句代码:
Product product = weakProductA.get();

实际上,对于这种情况,Java类库为我们提供了WeakHashMap类,使用和这个类,它的键自然就是弱引用对象,无需我们再手动包装原始对象。这样一来,当productA变为null时(表明它所引用的Product已经无需存在于内存中),这时指向这个Product对象的就是由弱引用对象weakProductA了,那么显然这时候相应的Product对象时弱可达的,所以指向它的弱引用会被清除,这个Product对象随即会被回收,指向它的弱引用对象会进入引用队列中。

下面我们来简单地介绍下引用队列的概念。实际上,WeakReference类有两个构造函数:

WeakReference(T referent) //创建一个指向给定对象的弱引用
WeakReference(T referent, ReferenceQueue<? super T> q) //创建一个指向给定对象并且登记到给定引用队列的弱引用

我们可以看到第二个构造方法中提供了一个ReferenceQueue类型的参数,通过提供这个参数,我们便把创建的弱引用对象注册到了一个引用队列上,这样当它被垃圾回收器清除时,就会把它送入这个引用队列中,我们便可以对这些被清除的弱引用对象进行统一管理。

原文地址:https://www.cnblogs.com/yuexiaoyun/p/12189267.html

时间: 2024-07-31 22:35:19

(特别篇)java集合(四)Map集合之WeakHashMap详解之弱引用详解的相关文章

java集合(List集合与Map集合的数据转换)

List集合与Map集合的数据转换 实现List和Map数据的转换. 具体要求如下: 功能1:定义方法public void listToMap( ){ }将List中Student元素封装到Map中 1)使用构造方法Student(int id,String name,int age,String sex )创建多个学生信息并加入List 2) 遍历List,输出每个Student信息 3) 将List中数据放入Map,使用Student的id属性作为key,使用Student对象信息作为va

java集合框架--Map集合

1.Map集合的概述 Map集合是将键映射到值的对象.一个映射不能包含重复的键.每个键最多只能映射到一个值. 2.Map接口和Collection接口的不同? Map集合存储元素是成对出现的,Collection集合存储元素是单独出现的. Map集合的键是唯一的,值是可重复的. Collection集合的子接口Set是唯一的,List是可重复的. Map集合的数据结构值针对键有效,和值无关,而Collection接口的数据结构是针对元素有效. 3.Map集合示例及功能 package cn; i

java学习笔记—集合之Map集合

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; font: 12.0px Times } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Songti SC" } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Times } p.p4 { margin: 0.0px 0.0px 0.0px 0.0

(1)集合 ---遍历map集合

Map接口     实现Map接口的类用来存储键(key)-值(value) 对.Map 接口的实现类有HashMap和TreeMap等.Map类中存储的键-值对通过键来标识,所以键值不能重复. HashMap: 线程不安全,效率高. 允许key或value为nullHashTable:线程安全,效率低. 不允许key或value为nullProperties : HashTable的子类,key和value都是string常用的方法: Object put(Object key, Object

Java基础知识强化之集合框架笔记52:Map集合之Map集合的遍历 键找值

1. Map集合的遍历  Map -- 夫妻对 思路:  A:把所有的丈夫给集中起来.  B:遍历丈夫的集合,获取得到每一个丈夫.  C:让丈夫去找自己的妻子.  转换:  A:获取所有的键  B:遍历键的集合,获取得到每一个键  C:根据键去找值 2. 代码示例: 1 package cn.itcast_01; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.Set; 6 7 public cla

Java基础知识强化之集合框架笔记53:Map集合之Map集合的遍历 键值对对象找键和值

1. Map集合的遍历(键值对对象找键和值) Map -- 夫妻对  思路:  A: 获取所有结婚证的集合  B: 遍历结婚证的集合,得到每一个结婚证  C: 根据结婚证获取丈夫和妻子 转换:  A: 获取所有键值对对象的集合  B: 遍历键值对对象的集合,得到每一个键值对对象  C: 根据键值对对象获取键和值 2. 代码示例: 1 package cn.itcast_01; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 impo

Java Collection、Map集合总结

1.Java中的Collection集合总结 Collection |---List(存储有序,可重复) |---ArrayList 底层数据结构是数组,查询快,增删慢. 线程不安全.效率高 |---Vector 底层数据结构是数组,查询快,增删慢. 线程安全.效率低. |---LinkedList 底层数据结构是链表,查询慢,增删快. 线程不安全,效率高 |---Set(存储无序,元素唯一) |---HashSet 底层数据结构是哈希表. 依赖hashCode()和equals()两个方法进行

Java基础知识强化之集合框架笔记51:Map集合之Map集合的功能概述与测试

1. Map集合的功能概述 (1)添加功能 V put(K key,V value):添加元素.这个其实还有另一个功能?先不告诉你,等会讲 如果键是第一次存储,就直接存储元素,返回null 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值 (2)删除功能 void clear():移除所有的键值对元素 V remove(Object key):根据键删除键值对元素,并把值返回 (3)判断功能 boolean containsKey(Object key):判断集合是否包含指定的键 bo

Java基础知识强化之集合框架笔记50:Map集合之Map集合的概述和特点

1. Map集合的概述: 1 public interface Map<K,V> 作为学生来说,是根据学号来区分不同的学生的,那么假设我现在已经知道了学生的学号,我要根据学号去获取学生姓名,请问怎么做呢?如果采用前面讲解过的集合,我们只能把学号和学生姓名作为一个对象的成员,然后存储整个对象,将来遍历的时候,判断,获取对应的名称.但是呢,如果我都能把学生姓名拿出来了,我还需要根据编号去找吗?针对我们目前的这种需求:仅仅知道学号,就想知道学生姓名的情况,Java就提供了一种新的集合 Map.通过查