具有String文字和String对象的weakhashmap的行为

时间:2014-05-27 04:44:08

标签: java weakhashmap

我理解WeakhashMap的概念。 String literal和String对象使其难以理解。

以下是代码:

package com.lnt.StringBuf;

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

public class Test1 {
    public static void main(String[] args) {

        Map w = new WeakHashMap();
        Map h = new HashMap<>();

        String hkey = new String("hashkey");
        String wkey = new String("weakkey");
    /*  String hkey = "hashkey";
        String wkey = "weakkey";*/

        h.put(hkey, 1);
        w.put(wkey, 1);

        System.gc();

        System.out.println("Before");
        System.out.println("hashmap size: " + h.size());
        System.out.println("weakmap size: " + w.size());
        System.out.println("Hashmap value: " + h.get("hashkey") + "\t"
                + "weakmap value: " + w.get("weakkey"));

        hkey = null;
        wkey = null;

        System.gc();
        System.out.println(hkey+" "+wkey);

        System.out.println("After");
        System.out.println("hashmap size: " + h.size());
        System.out.println("weakmap size: " + w.size());
        System.out.println("Hashmap value: " + h.get("hashkey") + "\t"
                + "weakmap value: " + w.get("weakkey"));

        System.out.println(h.entrySet());
        System.out.println(w.entrySet());

    }

}

输出是:

Before
hashmap size: 1
weakmap size: 1
Hashmap value: 1    weakmap value: 1
null null
After
hashmap size: 1
weakmap size: 0
Hashmap value: 1    weakmap value: null
[hashkey=1]
[]

但是什么时候 String hkey = new String(“hashkey”); String wkey = new String(“weakkey”);

替换为以下代码,输出更改。

String hkey = "hashkey";
String wkey = "weakkey";

输出是:

Before
hashmap size: 1
weakmap size: 1
Hashmap value: 1    weakmap value: 1
null null
After
hashmap size: 1
weakmap size: 1
Hashmap value: 1    weakmap value: 1
[hashkey=1]
[weakkey=1]

问题:在WeakHashMap中以不同的方式使String文字和String对象'null'受到影响。是什么原因?

3 个答案:

答案 0 :(得分:6)

字符串文字是实习的,这基本上意味着有一个缓存,通常称为字符串池。因此,字符串文字总是被强烈引用 - 使它们不适合用作弱结构中的键,例如WeakReferenceWeakHashMap

自动装箱的int也是如此:Integer为[{1}}对象保留Integer个值的缓存,范围为[-128,127]。所以你也不应该在弱结构中使用int来获取密钥。

但是,您可以通过在插入条目时创建新对象来解决这些问题,例如:在下面的示例中,“a”条目最终将从地图中删除,但“b”条目将永远保留在那里,这实际上是内存泄漏:

int

同样的例子对整数有效:

WeakHashMap<String, Object> map = new WeakHashMap<>();
map.add(new String("a"), new Object());
map.add("b", new Object());

由于WeakHashMap<Integer, Object> map = new WeakHashMap<>(); map.add(new Integer(56), new Object()); map.add(57, new Object()); 的缓存,57的条目将永远留在那里,但垃圾收集器可以删除56条目。

Integer也有缓存,但当然只有2个值。 Boolean具有256个潜在危险值,Integer实际上具有无限次出现可能是危险的 - 您只需使用文字(或使用String)来创建它们。可能还存在其他危险类别。

答案 1 :(得分:2)

  

使String literal和String对象'null'在不同的方面产生影响   在WeakHashMap中的方式。是什么原因?

首先,您无法创建对象null。您可以创建变量引用null或引用对象,但创建对象null不是存在的概念。

WeakHashMap个州的javadoc

  

WeakHashMap中的条目会在其密钥时自动删除   不再是一般用途。更准确地说,存在   给定密钥的映射不会阻止密钥被丢弃   由垃圾收集器,即,可以最终化,最终确定,和   然后回收。

在运行时,JVM为加载类时看到的每个String文字创建一个String对象。这些对象在加载它们的ClassLoader为GC之前无法进行GC控制,无论它们是否在WeakHashMap中被引用。

这与做

类似
String wkey =  new String("weak");
String other = wkey;

由于您可以在其他位置找到对象的可访问内容,因此即使在集合中使用,也无法进行GC操作。

另请注意,System.gc()并不保证垃圾收集会运行。使用它时要注意不要误解结果。

答案 2 :(得分:0)

如果用作键,则字符串不适用于WeakHashMap。这是因为,当创建String对象时,JVM也会在String池中创建对象。即使您使引用无效,它们仍可能在字符串池中保持强引用。

Map<String, String> stringWeakHashMap = new WeakHashMap<String, String>();
String str1 = "Key 1";
String str2 = "Key 2";

stringWeakHashMap.put(str1, "Value 1");
stringWeakHashMap.put(str2, "Value 2");
str1 = null;

System.gc();
System.out.println("Weak Hash Map :" + stringWeakHashMap.toString());

运行上面的代码后,生成的输出是

弱哈希地图:{键2 =值2,键1 =值1}