作者:n_light征蓝妙 | 来源:互联网 | 2023-01-16 15:21
我们需要缓存一些有关我们正在使用的对象的信息java.util.WeakHashMap
.如果我们关键是java.util.HashMap
我们看到了意想不到的行为.
例:
WeakHashMap whm = new WeakHashMap<>();
Map map = new HashMap<>();
whm.put(map, "map");
System.out.println(map + ": " + whm.get(map) + " " + whm + " " + whm.containsKey(map));
map.put("key", "value");
System.out.println(map + ": " + whm.get(map) + " " + whm + " " + whm.containsKey(map));
System.out.println(map.hashCode());
System.out.println(whm.entrySet().stream().map(e -> e.getKey().hashCode()).collect(Collectors.toList()));
System.out.println(whm.entrySet().stream().map(e -> e.getKey() == map).collect(Collectors.toList()));
输出是:
{}: map {{}=map} true
{key=value}: null {{key=value}=map} false
112004910
[112004910]
[true]
whm.get(map)
null
打电话后为什么whm.put(map, "map")
?
同样的结果java.util.HashSet
......
因为AtomicInteger
它按预期工作:
WeakHashMap whm = new WeakHashMap<>();
AtomicInteger integer = new AtomicInteger(0);
whm.put(integer, "integer");
System.out.println(integer + ": " + whm.get(integer) + " " + whm + " " + whm.containsKey(integer));
integer.set(1);
System.out.println(integer + ": " + whm.get(integer) + " " + whm + " " + whm.containsKey(integer));
结果是:
0: integer {0=integer} true
1: integer {1=integer} true
Jon Skeet..
8
这与它是一个弱映射无关,而且与修改映射键有关,这基本上是你应该避免做的事情.通过向地图添加条目,您将更改其哈希码.这很容易证明:
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map map = new HashMap<>();
System.out.println(map.hashCode());
map.put("key", "value");
System.out.println(map.hashCode());
}
}
此时,尝试获取条目将失败,因为其哈希码不再与插入的哈希码匹配.
AtomicInteger
不会覆盖equals
或者hashCode
,所以你得到对象标识相等 - 它的哈希码在你调用时不会改变set
.
1> Jon Skeet..:
这与它是一个弱映射无关,而且与修改映射键有关,这基本上是你应该避免做的事情.通过向地图添加条目,您将更改其哈希码.这很容易证明:
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map map = new HashMap<>();
System.out.println(map.hashCode());
map.put("key", "value");
System.out.println(map.hashCode());
}
}
此时,尝试获取条目将失败,因为其哈希码不再与插入的哈希码匹配.
AtomicInteger
不会覆盖equals
或者hashCode
,所以你得到对象标识相等 - 它的哈希码在你调用时不会改变set
.