当前位置: 首页 > 面试题库 >

如何在Java Maps中将Set用作键

云霖
2023-03-14
问题内容

我有一个使用Set作为键类型的Map,如下所示:

Map<Set<Thing>, Val> map;

当我查询map.containsKey(myBunchOfThings)时,它返回false,我不明白为什么。我可以遍历键集中的每个键,并验证是否有一个键,其中(1)具有相同的hashCode,并且(2)等于myBunchOfThings的equals()。

System.out.println(map.containsKey(myBunchOfThings)); // false.
for (Set<Thing> k : map.keySet()) {
  if (k.hashCode() == myBunchOfThings.hashCode() && k.equals(myBunchOfThings) {
     System.out.println("Fail at life."); // it prints this.
  }
}

我是否会从根本上误解containsKey的合同?使用集(或更一般而言,集合)作为映射键是否有秘密?


问题答案:

在地图中使用键时,请勿更改键。在Mapjava的医生说:

注意:如果将可变对象用作地图键,则必须格外小心。如果在对象是映射中的键的情况下以影响等值比较的方式更改对象的值,则不会指定映射的行为。此禁止的一种特殊情况是,不允许地图包含自身作为键。虽然允许映射包含自身作为值,但建议格外小心:在此类映射上不再很好地定义equals和hashCode方法。

我知道这个问题,但直到现在都没有进行过测试。我再详细说明一下:

   Map<Set<String>, Object> map  = new HashMap<Set<String>, Object>();

   Set<String> key1 = new HashSet<String>();
   key1.add( "hello");

   Set<String> key2 = new HashSet<String>();
   key2.add( "hello2");

   Set<String> key2clone = new HashSet<String>();
   key2clone.add( "hello2");

   map.put( key1, new Object() );
   map.put( key2, new Object() );

   System.out.println( map.containsKey(key1)); // true
   System.out.println( map.containsKey(key2)); // true
   System.out.println( map.containsKey(key2clone)); // true

   key2.add( "mutate" );

   System.out.println( map.containsKey(key1)); // true
   System.out.println( map.containsKey(key2)); // false
   System.out.println( map.containsKey(key2clone)); // false (*)

   key2.remove( "mutate" );

   System.out.println( map.containsKey(key1)); // true
   System.out.println( map.containsKey(key2)); // true
   System.out.println( map.containsKey(key2clone)); // true

之后key2发生突变时,地图不包含它了。我们可以认为地图在添加数据时会“索引”数据,然后我们期望它仍然包含key2克隆(标有的行*)。但是有趣的是,事实并非如此。

因此,正如java doc所说的那样,不应对键进行突变,否则行为 未指定 。期。

我想这就是您的情况。



 类似资料:
  • 问题内容: 我想将数组转换为Java中的Set。有一些明显的方法可以做到这一点(例如,使用循环),但是我想要一些更整洁的东西,例如: 有任何想法吗? 问题答案: 像这样: 在Java 9+中,如果设置不可修改,则可以: 在Java 10+中,可以从数组组件类型推断出泛型类型参数:

  • 问题内容: 我有几个,并且想要将它们中的每一个转换成单个String,其中原始元素的每个元素Set都由空格“”分隔。天真的第一方法就是这样做 谁能想到更快,更漂亮或更有效的方式来做到这一点? 问题答案: 更新: 重新阅读此答案,我现在希望使用有关番石榴木匠的其他答案。实际上,这些天我不接近apache commons。 另一个更新: Java 8引入的方法 String.join() 尽管它不像G

  • 问题内容: 有没有一种方法可以将类型依赖项添加到我的POM并获取其所有模块? JavaMail是一个很好的例子。Maven Central Repo的父POM名为:com.sun.mail:all:1.5.0,模块包括:mail,mailapi,mailapijar,smtp,imap,gimap,pop3和dsn。 但是,“所有”人工制品只有一个文件: 是否可以将“所有”人工制品添加为对我的PO

  • 本文向大家介绍在 Java 中将 List 转换为 Set,包括了在 Java 中将 List 转换为 Set的使用技巧和注意事项,需要的朋友参考一下 假设以下是带有字符串值的列表- 现在,将上面的列表转换为set- 示例 以下是在Java中将List转换为Set的程序- 输出结果

  • 问题内容: 我正在尝试将Integer数组添加到Set中,如下所示: 我收到以下错误提示, 其次,我也尝试按照以下步骤进行操作,但仍然出现错误, 如何在Java中正确地将Integer数组添加到Set中?谢谢。 问题答案: 您需要使用包装器类型才能使用 或 手动添加元素,例如 最后,如果您需要保留插入顺序,则可以使用。

  • 我目前正在尝试为我一直在研究的Mandelbrot Set代码实现缩放功能。这个想法是放大/缩小我左/右键单击的地方。到目前为止,每当我点击屏幕,分形确实会放大。问题是分形不是在原点呈现的——换句话说,它没有在我想要的点上放大。我希望通过这里,我可以获得代码审查和概念上的理解,了解如何放大一个点。 以下是我在使用转义算法之前如何转换像素坐标的: MandelBrot.碎片 在我的左键点击手柄上,我