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

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

结果是

 [a, b, c] [a, b, d] [a, b, c] 

其中[a,b,c]重复,因此散列函数不能按预期工作。 我将如何重写String数组的Hash方法。 或者就此而言,通用数组? 有没有更好的方法来完成我想要做的事情?

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

请改用一组列表。

“更好的方法”是使用集合。 使用List而不是String[]

 Set> 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 

编辑

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

 Set boog = new TCustomHashSet(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 { public int computeHashCode(Object[] array) { return Arrays.hashCode(array); } public boolean equals(Object[] arr1, Object[] arr2) { return Arrays.equals(arr1, arr2); } } 

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

您可以使用List ,使用基于其元素的哈希码计算的hashCode()ArrayList (与大多数实现一样)使用这样的函数。


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

您实际上正在使用默认的hashCode方法为所有不同的数组返回不同的值!

解决此问题的最佳方法是使用Collection (例如ListSet )或定义自己的包装类,例如:

 public class StringArray { public String[] stringArray; [...] // constructors and methods @Override public int hashCode() { final int prime = 31; int result = 1; for(String string : stringArray){ result = prime * result + ((string == null) ? 0 : string.hashCode()); } } } 

这个类实际上使用与List相同的hashCode方法。

你现在处理:

 HashSet boog = new HashSet(); 

实际上,你可以。 您可以使用提供的Comparator TreeSet 。 在你的情况下,它将是这样的:

 Set boog = new TreeSet<>((o1, o2) -> { for (int i = 0; i < o1.length; i++){ int cmp = o1[i].compareTo(o2[i]); if (cmp != 0) { return cmp; } } return o1.length - o2.length; }); 

在引擎盖下它看起来像字母排序树。