【发布时间】:2014-06-18 17:45:33
【问题描述】:
我计划将 Google 的缓存实现 (com.google.common.cache.Cache) 与 java.util.set 一起使用。下面的代码块显示了使用Set.contains() 检查集合中是否存在元素的结果。
当Set的元素类型为java.util.Map时,它实际上是在检查传递的映射的key和Value是否与Set中找到的任何元素相似。所以我的理解是调用 Key 和 Value 对象equals() 方法来检查是否有任何元素具有相同的值。
另一方面,Google 的实现似乎使用了obj1==obj2 类型比较。
final Map<Integer, Integer> map = new HashMap<>();
map.put(1,1);
final Map<Integer, Integer> map2 = new HashMap<>();
map2.put(1,1);
Set<Map<Integer, Integer>> s2 = new HashSet<>();
s2.add(map);
System.out.println("Set.contains() check with a different instance of java.util.Map but same (key,value)=>(1,1): "+s2.contains(map2));
final Cache<Integer, Integer> cache = CacheBuilder.newBuilder().expireAfterWrite(10L, TimeUnit.MINUTES).build();
cache.put(1,1);
final Cache<Integer, Integer> cache2 = CacheBuilder.newBuilder().expireAfterWrite(10L, TimeUnit.MINUTES).build();
cache2.put(1,1);
Set<Cache<Integer,Integer>> s = new HashSet<>();
s.add(cache);
System.out.println("Set.contains() check with a different instance of com.google.common.cache.Cache but same (key,value)=>(1,1): "+s.contains(cache2));
这是上面代码的输出。
Set.contains() check with a different instance of java.util.Map but same (key,value)=>(1,1): true
Set.contains() check with a different instance of com.google.common.cache.Cache but same (key,value)=>(1,1): false
我的问题是:
这是预期的行为还是错误?
或者我在执行的测试中遗漏了什么?
如果有人对 Google 的缓存实现有更好的了解,我也将不胜感激,如果这是一个已知问题,请告诉我一些想法。
谢谢。
【问题讨论】:
-
请注意,在任何情况下,将 mutable 对象(如地图)放入
HashSet是非常危险的。即使 IF 您的示例也有效:当您在将map对象放入集合s2后对其进行修改时,集合s2将变得不一致。 (这意味着即使您之后对map2进行了相同的修改,查找很可能不再起作用,并且第一个输出也会打印false!) -
我同意这可能会导致问题,但在这种特定情况下,我只是在添加之前检查集合中是否存在元素,而不是修改元素。
-
“已知问题”让人觉得这不是预期的行为。
-
@LouisWasserman 不是说这是一个问题(已知或未知:) )只是询问是否有没有实施深度平等的原因,或者 Guava 团队只是将其保留为现在。或者如果我误解了它应该如何工作。或者,在比较对象时,缓存的行为方式与地图的行为方式相同。
标签: java collections guava