弱散列映射WeakHashMap

WeakHashMap解决了什么问题?

设计WeakHashMap类是为了解决一个有趣的问题。如果有一个值,对应的键已经不再使用了,将会出现什么情况呢?假定对某个键的最后一次引用已经消亡,不再有任何途径引用这个值的对象了。但是,由于在程序中的任何部分没有再出现这个键,所以,这个键/值对无法从映射中删除。为什么垃圾回收器不能够删除它呢?难道删除无用的对象不是垃圾回收器的工作吗?

遗憾的是,事情没有这样简单。垃圾回收器跟踪活动的对象。只要映射对象是活动的,其中的所有桶也是活动的,它们不能被回收。因此,需要由程序负责从长期存活的映射表中删除那些无用的值。或者使用WeakHashMap完成这件事情。当对键的唯一引用来自散列条目时,这一数据结构将与垃圾回收器协同工作一起删除键/值对。

下面是这种机制的内部运行情况。WeakHashMap使用弱引用(weak references)保存键。WeakReference对象将引用保存到另外一个对象中,在这里,就是散列键。对于这种类型的对象,垃圾回收器用一种特有的方式进行处理。通常,如果垃圾回收器发现某个特定的对象已经没有他人引用了,就将其回收。然而,如果某个对象只能由 WeakReference引用,垃圾回收器仍然回收它,但要将引用这个对象的弱引用放人队列中。WeakHashMap将周期性地检查队列,以便找出新添加的弱引用。一个弱引用进人队列意味着这个键不再被他人使用,并且已经被收集起来。于是,WeakHashMap将删除对应的条目。

摘自Java核心技术 卷1(第十版)

WeakHashMap回收测试

 1 @Test
 2     public void Test3() {
 3         String s1 = new String("s1");
 4         String s2 = new String("s2");
 5         String s3 = new String("s3");
 6         Map<String, Integer> map = new WeakHashMap<>();
 7         map.put(s1, 1);
 8         map.put(s2, 2);
 9         map.put(s3, 3);
10         map.forEach((K, V) -> System.out.println("GC回收前[" + K + ", " + V + "]"));
11         s2 = null;
12         System.gc();
13         System.out.println();
14         map.forEach((K, V) -> System.out.println("GC回收后[" + K + ", " + V + "]"));
15     }

输出结果:

GC回收前[s2, 2]
GC回收前[s1, 1]
GC回收前[s3, 3]

GC回收后[s1, 1]
GC回收后[s3, 3]

注意:如果Key为字面量时,WeakHashMap回收机制失效。

例如:

 1 @Test
 2     public void Test4() {
 3         String s1 = "s1";
 4         String s2 = "s2";
 5         String s3 = "s3";
 6         Map<String, Integer> map = new WeakHashMap<>();
 7         map.put(s1, 1);
 8         map.put(s2, 2);
 9         map.put(s3, 3);
10         map.forEach((K, V) -> System.out.println("GC回收前[" + K + ", " + V + "]"));
11         s2 = null;
12         System.gc();
13         System.out.println();
14         map.forEach((K, V) -> System.out.println("GC回收后[" + K + ", " + V + "]"));
15     }

输出结果:

GC回收前[s2, 2]
GC回收前[s1, 1]
GC回收前[s3, 3]

GC回收后[s2, 2]
GC回收后[s1, 1]
GC回收后[s3, 3]

原文地址:https://www.cnblogs.com/mybdss/p/9160878.html

时间: 2024-11-08 22:51:44

弱散列映射WeakHashMap的相关文章

栈,散列映射

栈的方法 public void push(E item) public E pop() public boolean empty() public E peek()//获得栈顶数据 public int search(Oject data)//查找栈是否有data项,没有返回-1 HashMap散列映射 HashMap<String,V> 方法 public void put(Key k,Value v)//加入 public void clear()//清空散列映射 public bool

java 散列与散列码探讨 ,简单HashMap实现散列映射表运行各种操作示列

package org.rui.collection2.maps; /** * 散列与散列码 * 将土拔鼠对象与预报对象联系起来, * @author lenovo * */ //土拨鼠 public class Groundhog { protected int number; public Groundhog(int n) { number=n; } @Override public String toString() { return "Groundhog #" + number

java 散列与散列码探讨 ,简单HashMap实现散列映射表执行各种操作示列

package org.rui.collection2.maps; /** * 散列与散列码 * 将土拔鼠对象与预报对象联系起来, * @author lenovo * */ //土拨鼠 public class Groundhog { protected int number; public Groundhog(int n) { number=n; } @Override public String toString() { return "Groundhog #" + number

PTA 字符串关键字的散列映射(25 分)

7-17 字符串关键字的散列映射(25 分) 给定一系列由大写英文字母组成的字符串关键字和素数P,用移位法定义的散列函数H(Key)将关键字Key中的最后3个字符映射为整数,每个字符占5位:再用除留余数法将整数映射到长度为P的散列表中.例如将字符串AZDEG插入长度为1009的散列表中,我们首先将26个大写英文字母顺序映射到整数0~25:再通过移位将其映射为3×32?2??+4×32+6=3206:然后根据表长得到,即是该字符串的散列映射位置. 发生冲突时请用平方探测法解决. 输入格式: 输入第

PTA数据结构与算法题目集(中文) 7-43字符串关键字的散列映射 (25 分)

PTA数据结构与算法题目集(中文)  7-43字符串关键字的散列映射 (25 分) 7-43 字符串关键字的散列映射 (25 分) 给定一系列由大写英文字母组成的字符串关键字和素数P,用移位法定义的散列函数(将关键字Key中的最后3个字符映射为整数,每个字符占5位:再用除留余数法将整数映射到长度为P的散列表中.例如将字符串AZDEG插入长度为1009的散列表中,我们首先将26个大写英文字母顺序映射到整数0~25:再通过移位将其映射为3:然后根据表长得到,即是该字符串的散列映射位置. 发生冲突时请

C++学习笔记 &lt;hash_map&gt; &lt;散列映射&gt;

对于大型容器而言hash_map要比map快5至10倍的元素查找速度. map对其元素类型要求有一个<,hash_map要求一个==和一个散列函数. map<string,int>  m1;   //用<比较串 map<string,int Nocase>   m2;       //用Nocase()比较串 hash_map<string,int>   hm1;        //用Hash<string>()散列,用==比较 hash_map

案例5-1.3 整型关键字的散列映射 (25分)--散列表(除留余数法+线性探测法)

解题思路: 1.初始化散列表,用于标记散列地址是否已用 2.构造结构体,(关键字去重)记录关键字的值和地址 3.读入数据,判断该关键字是否重复查询 4.用辅助数组记录每个关键字的地址,遍历输出 #include <stdio.h> #include <string.h> typedef struct { int key; int value; } Hash; int main() { int n,p; scanf("%d %d",&n,&p);

HashMap实现 Hash优化与高效散列

OverView Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable, except that it is unsynch

容器深入研究 --- 散列与散列码(二)

为速度而散列: SlowMap.java说明了创建一个新的Map并不困难.但正如它的名称SlowMap所示,它不会很快,如果有更好的选择就应该放弃它.它的问题在于对键的查询,键没有按照任何特定的顺序保存,所以只能使用简单的线性查询,而线性查询是最慢的查询方式. 散列的价值在于速度: 散列使得查询得以快速进行.由于瓶颈在于键的查询速度,因此解决方案之一就是保持键的排序状态,然后使用Collections.binarySearch()进行查询. 散列则更进一步,它将键保存在某处,以便能够很快的找到.