HashSet是根据元素的hash值来查找的,HashMap也是根据key的hash来查找的。如果先添加了元素,然后又在外面单独对元素做修改,很可能导致再次查找时找不到,因为这个元素的hash值已经被修改了。这并不是出现在所有的数据类型中,只会出现在那些根据自身值或属性计算hash值,而修改时又恰好是修改这些的。
下面做个测试,
System.out.println("----int----");
int a = 2;
Set<Integer> set = new HashSet<>();
set.add(a);
a = 3;
System.out.println(set.contains(a)); //false
System.out.println(set.contains(2)); //true
System.out.println("----String----");
String s = "22";
Set<String> set1 = new HashSet<>();
set1.add(s);
s = "33";
System.out.println(set1.contains(s)); //false
System.out.println(set1.contains("22")); //true
System.out.println("----StringBuilder----");
StringBuilder sb = new StringBuilder("22");
Set<StringBuilder> set2 = new HashSet<>();
set2.add(sb);
sb.append('3');
System.out.println(set2.contains(sb)); //true
System.out.println("---HashMap + String---");
Map<String, Integer> map = new HashMap<>();
map.put(s,a);
s = "44";
a = 4;
System.out.println(map.getOrDefault(s,100)); //100
System.out.println(map.getOrDefault("33", 100)); //3
String是根据自身的每个字符去计算hash值的,修改了,对象指向了新一块内存,有了新的hash值,但集合仍持有原来的引用,导致再按s的hash去查找找不到,同时"22"的内存无法释放,发生内存泄漏。
其他的原因类似。