概述

在这篇文章中,我们将探索 java.util 包中的WeakHashMap。

为了理解数据结构,我们将在这里使用它来推出一个简单的缓存实现。但是,请记住,这是为了了解地图的工作原理,并且创建自己的缓存实现几乎总是一个坏主意。

简而言之,WeakHashMap是Map接口的基于哈希表的实现,其键为WeakReference类型。

当WeakHashMap中的某个条目不再被普通使用时,该条目将被自动删除,这意味着没有单个Reference 指向该键。当垃圾回收(GC)进程丢弃某个键时,其条目将有效地从映射中删除,因此此类的行为与其他Map实现有所不同。

Strong, Soft, and Weak References

要了解WeakHashMap的工作原理,我们需要查看WeakReference类 -这是WeakHashMap实现中键的基本构造。在Java中,我们有三种主要的引用类型,我们将在以下各节中进行解释。

强引用

强引用是我们在日常编程中使用的最常见的引用类型:

Integer prime = 1; 变量prime具有对值为1 的Integer对象的强引用。任何具有指向其的强引用的对象均不适合使用GC。

弱引用

简而言之,只有在JVM绝对需要内存之前,才会对具有SoftReference 指向该对象的对象进行垃圾回收。

让我们看看如何在Java中创建SoftReference:

Integer prime = 1;

SoftReference soft = new SoftReference(prime);

prime = null;

该主要对象有指向它很强的借鉴意义。

接下来,我们将主要的强引用包装为软引用。将强引用设为null之后,素对象可以使用GC,但仅在JVM绝对需要内存时才收集该对象。

虚引用

仅弱引用所引用的对象会被紧急收集;在这种情况下,GC不会等到需要内存。

我们可以通过以下方式在Java中创建WeakReference:

Integer prime = 1;

WeakReference soft = new WeakReference(prime);

prime = null;

当我们将主要引用设为null时,主要对象将在下一个GC周期中被垃圾回收,因为没有其他强引用指向该对象。

WeakReference类型的引用在WeakHashMap中用作键。

WeakHashMap作为高效的内存缓存

假设我们要建立一个缓存,将大图像对象保留为值,并将图像名称保留为键。我们想选择一个合适的地图实现来解决该问题。

使用简单的HashMap将不是一个好的选择,因为值对象可能会占用大量内存。而且,即使它们不再在我们的应用程序中使用,它们也永远不会被GC进程从缓存中回收。

理想情况下,我们需要一个Map实现,该实现允许GC自动删除未使用的对象。当我们的应用程序中任何地方都没有使用大图像对象的键时,该条目将从内存中删除。

幸运的是,WeakHashMap具有这些特征。让我们测试一下WeakHashMap并观察其行为:

WeakHashMap map = new WeakHashMap<>();

BigImage bigImage = new BigImage("image_id");

UniqueImageName imageName = new UniqueImageName("name_of_big_image");

map.put(imageName, bigImage);

assertTrue(map.containsKey(imageName));

imageName = null;

System.gc();

await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty);

我们正在创建一个WeakHashMap实例,该实例将存储我们的BigImage对象。我们将BigImage对象作为值,并将imageName对象引用作为键。的imageName将被存储在一个图作为WeakReference的类型。

接下来,我们将imageName引用设置为null,因此不再有指向bigImage对象的引用。WeakHashMap的默认行为是在下一个GC上回收没有引用的条目,因此该条目将在下一个GC进程中从内存中删除。

我们正在调用System.gc()来强制JVM触发GC进程。GC周期结束后,我们的WeakHashMap将为空:

WeakHashMap map = new WeakHashMap<>();

BigImage bigImageFirst = new BigImage("foo");

UniqueImageName imageNameFirst = new UniqueImageName("name_of_big_image");

BigImage bigImageSecond = new BigImage("foo_2");

UniqueImageName imageNameSecond = new UniqueImageName("name_of_big_image_2");

map.put(imageNameFirst, bigImageFirst);

map.put(imageNameSecond, bigImageSecond);

assertTrue(map.containsKey(imageNameFirst));

assertTrue(map.containsKey(imageNameSecond));

imageNameFirst = null;

System.gc();

await().atMost(10, TimeUnit.SECONDS)

.until(() -> map.size() == 1);

await().atMost(10, TimeUnit.SECONDS)

.until(() -> map.containsKey(imageNameSecond));

请注意,只有imageNameFirst引用设置为null。该imageNameSecond参考保持不变。触发GC后,映射将仅包含一个条目– imageNameSecond。

java weakhashmap用法_Java WeakHashMap指南相关推荐

  1. java list用法_Java List 用法详解及实例分析

    Java List 用法详解及实例分析 Java中可变数组的原理就是不断的创建新的数组,将原数组加到新的数组中,下文对Java List用法做了详解. List:元素是有序的(怎么存的就怎么取出来,顺 ...

  2. java treemap用法_Java TreeMap put()用法及代码示例

    TreeMap的java.util.TreeMap.put()方法用于将映射插入Map.这意味着我们可以将特定的键及其映射到的值插入到特定的映射中.如果传递了现有键,则以前的值将被新值替换.如果传递了 ...

  3. java future用法_Java中的多线程知识点

    如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...

  4. java return用法_Java枚举的高级用法之多键值的映射使用

    枚举Enum单映射使用 做Java的各位仁兄姐妹都知道,Java通过HashMap,以及枚举提供了方便的K-V映射功能,例如 枚举单映射使用 但是如果遇到多个键值映射,例如K-K-V的形式怎么办呢?可 ...

  5. java foreach用法_Java十大简单性能优化

    以下是Java中最容易进行的10个性能优化: 1.使用StringBuilder 这几乎是所有Java代码中的默认设置.尽量避免+操作员.当然,您可能会争辩说它StringBuilder无论如何都是语 ...

  6. java list用法_java list的用法详解

    java list的用法详解 java中可变数组的原理就是不断的创建新的数组,将原数组加到新的数组中.以下是百分网小编搜索整理的关于java list的用法详解,需要的朋友可以参考一下!想了解更多相关 ...

  7. java instanceof用法_Java基础高频面试题汇总(1.4W字详细解析)

    注:由于公众号文章推送规则的改变,所以为了大家能够准时收到我们的文章推送,请记得将公众号:JAVA编程语言 设为星标-这样就不会错过每一篇精彩的推送啦~ 1. Java语言有哪些特点 (1)简单易学. ...

  8. java pattern用法_Java Pattern和Matcher用法

    Pattern用法 Java正则表达式通过java.util.regex包下的Pattern和Matcher类实现 Pattern类用于创建一个正则表达式,也可以说是创建一个匹配模式,可以通过两个静态 ...

  9. equals java的用法_Java ConcurrentLinkedDeque equals()用法及代码示例

    java.util.ConcurrentLinkedDeque类的equals()方法用于比较指定对象与此ConcurrentLinkedDeque是否相等.当且仅当指定对象也是ConcurrentL ...

最新文章

  1. request 对象和 response 对象
  2. python时间变量_python的对象 变量
  3. 哈尔滨商业大学计算机与信息工程学院地址,计算机与信息工程学院
  4. “大数据系统软件国家工程实验室”建设项目通过验收
  5. xib自动布局的时候,label高度计算误差问题
  6. ECCV2020论文-稀疏性表示-Neural Sparse Representation for Image Restoration翻译
  7. python调试网页_Python Django shell 调试
  8. 【通知】2020年有三AI-CV夏季划升级,更多项目,更高难度,更加落地
  9. mysql 整个数据库_mysql 整个数据库
  10. web前端常用知识点
  11. 最小二乘估计_相关性及最小二乘估计【20201026】
  12. C# 实现将文本txt生成图片
  13. ajax全局加密,Ajax请求接口加密研究(针对网页前端的接口安全加密机制研究)...
  14. 「mac操作指南」WidsMob HEIC将HEIC/HEIF 转换为 JPEG/PNG/TIFF格式
  15. 新版IAR软件打开旧版本创建的项目时出现的三个错误及其解决方案 is too long for segment definition
  16. 《多媒体技术与应用》练习题
  17. 42步进电机转速力矩曲线_42步进电机转速范围说明(28步进电机转速测试)
  18. Android MVVM框架搭建(一)ViewModel + LiveData + DataBinding
  19. JAVA中将汉字转化为首字母大写或拼音的格式
  20. 内窥镜胶囊(胶囊内镜)硬件方案

热门文章

  1. R方差分析(anova)以及Tukey检验
  2. LDNFSGB: prediction of long non-coding rna and disease association using network feature similarity
  3. oracle ora 13011,ORA-00600: internal error code, arguments: [13011]
  4. 电脑服务器高配置和高性能,为高性能工作站服务 超算系统配置推荐
  5. java中怎么放入.jpg_Java如何设置jpg质量
  6. tensorflow tf.keras.losses.MeanSquaredError 均方差损失函数 示例
  7. pycharm的anaconda配置
  8. 【Kaidi安装问题】下载mkl过慢
  9. oracle 加号和on,Oracle中连接与加号(+)的使用
  10. python mysql 分页_利用python对mysql表做全局模糊搜索并分页实例