在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
数组的hashCode()
使用默认实现,它没有考虑元素,你不能改变它。
您可以使用List
,使用基于其元素的哈希码计算的hashCode()
。 ArrayList
(与大多数实现一样)使用这样的函数。
或者(但不太可取,除非你被迫以某种方式使用数组),你可以使用’特殊’ HashSet
,而不是调用key.hashCode()
调用Arrays.hashCode(array)
。 实现扩展HashMap
然后使用Collections.newSetFromMap(map)
您实际上正在使用默认的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()); } } }
这个类实际上使用与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; });
在引擎盖下它看起来像字母排序树。