【问题标题】:java.util.Map and google cache implementation(com.google.common.cache.Cache) differencejava.util.Map和google缓存实现(com.google.common.cache.Cache)的区别
【发布时间】:2014-06-18 17:45:33
【问题描述】:

我计划将 Google 的缓存实现 (com.google.common.cache.Cache) 与 java.util.set 一起使用。下面的代码块显示了使用Set.contains() 检查集合中是否存在元素的结果。

Set的元素类型为java.util.Map时,它实际上是在检查传递的映射的keyValue是否与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


【解决方案1】:

这是因为 HashMapequal() 实现提供了深度相等检查,而 guava Cache 没有提供它从 Object 中使用的这种相等方法

【讨论】:

    【解决方案2】:

    缓存故意使用引用相等,因为不同缓存的相等意义不大:如果一毫秒后,其中一个条目过期,则缓存不再相等。

    如果您想要内容平等,那么有一个简单的解决方法:cache1.asMap().equals(cache2.asMap())

    【讨论】:

      猜你喜欢
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 2014-09-24
      • 2010-10-26
      • 2014-03-03
      • 1970-01-01
      • 1970-01-01
      • 2019-12-01
      相关资源
      最近更新 更多