在Set中存储数组并避免重复

Boo*_*ker 25 java arrays generics hash set

HashSet<String[]> boog = new HashSet<String[]>();
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "d"});
Run Code Online (Sandbox Code Playgroud)

结果是

[a, b, c]
[a, b, d]
[a, b, c]
Run Code Online (Sandbox Code Playgroud)

这里[a,b,c]是重复的,所以预期的哈希函数不能正常工作.我将如何重写String数组的Hash方法.或者就此而言,通用数组?有没有更好的方法来完成我想要做的事情?

Sea*_*oyd 35

你不能.数组使用默认的基于身份的Object.hashCode()实现,你无法覆盖它.不要将数组用作HashMap/HashSet中的键!

请改用一组列表.


Mar*_*ers 26

"更好的方法"是使用集合.使用List而不是String[]:

Set<List<String>> boog = //...
boog.add(Arrays.asList("a", "b", "c"));
boog.add(Arrays.asList("a", "b", "c"));
boog.add(Arrays.asList("a", "b", "d"));

System.out.println(boog.size()); // 2
Run Code Online (Sandbox Code Playgroud)

编辑

如果您绝对需要使用数组作为键,则可以围绕每个键构建一个透明包装并将其放在地图中.有些图书馆会帮助您.例如,以下是Set<String[]>使用Trove的方法:

Set<String[]> boog = new TCustomHashSet<String[]>(new ArrayHashingStrategy());

boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "c"});
boog.add(new String[]{"a", "b", "d"});

System.out.println(boog.size()); // 2

//...
public class ArrayHashingStrategy extends HashingStrategy<Object[]> {

   public int computeHashCode(Object[] array) {
      return Arrays.hashCode(array);
   }

   public boolean equals(Object[] arr1, Object[] arr2) {
      return Arrays.equals(arr1, arr2);
   }
}        
Run Code Online (Sandbox Code Playgroud)


Boz*_*zho 5

hashCode() of arrays 使用默认实现,它没有考虑元素,你不能改变它。

您可以使用 aList代替, a 是hashCode()根据其元素的哈希码计算的。ArrayList(作为大多数实现)使用这样的功能。


或者(但不太可取,除非您被迫以某种方式使用数组),您可以使用“特殊” HashSetwhere 而不是调用key.hashCode()invoke Arrays.hashCode(array)。要实现该扩展HashMap然后使用Collections.newSetFromMap(map)

  • 后一种方法的问题在于 HashSet 在内部使用 HashMap,因此您也必须为其提供替代品。HashMap 位于私有字段中,因此您必须使用 Reflection 来实现。乱。 (2认同)