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"});
结果
[a, b, c]
[a, b, d]
[a, b, c]
其中[a,b,c]
重复,因此散列函数未按预期工作。我将如何重写String数组的Hash方法。或者就此而言,通用数组?有没有更好的方法来完成我想要做的事情?
答案 0 :(得分:32)
你做不到。数组使用默认的基于身份的Object.hashCode()实现,你无法覆盖它。不要在ArshMap / HashSet中使用Arrays作为键!
改为使用一组列表。
答案 1 :(得分:24)
“更好的方式”是使用集合。使用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
如果您绝对需要使用数组作为键,则可以围绕每个键构建一个透明包装并将其放在地图中。有些图书馆会帮助您。例如,以下是使用Trove进行Set<String[]>
的方法:
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);
}
}
答案 2 :(得分:4)
hashCode()
数组使用默认实现,但没有考虑元素,也无法更改。
您可以改为使用List
,并根据其元素的哈希码计算hashCode()
。 ArrayList
(与大多数实现一样)使用此类函数。
或者(但不太可取,除非你被迫以某种方式使用数组),你可以使用“特殊”HashSet
而不是调用key.hashCode()
调用Arrays.hashCode(array)
。要实现该扩展HashMap
,然后使用Collections.newSetFromMap(map)
答案 3 :(得分:1)
您实际上正在使用默认的hashCode
方法为所有不同的数组返回不同的值!
解决此问题的最佳方法是使用Collection
(例如List
或Set
)或定义自己的包装类,例如:
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());
}
}
}
此类实际上使用与hashCode
几乎相同的List
方法。
您现在处理:
HashSet<StringArray> boog = new HashSet<StringArray>();
答案 4 :(得分:0)
实际上,你可以。您可以使用提供的TreeSet
Comparator
。
在你的情况下,它将是:
Set<String[]> 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;
});
在引擎盖下,它看起来像字母排序的树。