将具有相同值的数组添加到HashSet会导致重复项

我正在尝试创建一组int的数组,问题是如果我尝试这样做:

HashSet s = new HashSet(); int a1[] = {1,2,3}; int a2[] = {1,2,3}; s.add(a1); s.add(a2) System.out.println(s.size()); 

然后s有两个对象,但应该只有一个。 注意:如果它是HashSet 则无关紧要。 它只是不起作用。

现在,如果我尝试使用ArrayList 执行此操作,请执行以下操作:

 HashSet<ArrayList> s = new HashSet<ArrayList>(); ArrayList a1 = new ArrayList(); ArrayList a2 = new ArrayList(); a1.add(1); a1.add(2); a1.add(3); a2.add(1); a2.add(2); a2.add(3); s.add(a1); s.add(a2) System.out.println(s.size()); 

然后s有一个对象。

我虽然有办法避免第一个代码中的错误,并将每个数组的哈希码存储在一个hashset中,如下所示:

 int a1[] = {0,10083,10084,1,0,1,10083,0,0,0,0}; int a2[] = {1 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0,2112}; HashSet s= new HashSet();//hashcodes of each array s.add(Arrays.hashCode(a1)); s.add(Arrays.hashCode(a2)); System.out.println(Arrays.hashCode(a1)); System.out.println(Arrays.hashCode(a2)); System.out.println(s.size()); 

它适用于第一种情况(1,2,3),但是在有碰撞的情况下它不起作用,所以我必须管理碰撞。 所以,我认为我正在做的是自己实现一个HashSet。

使用HashSet <ArrayList >它可以很好地工作。 我想在这种情况下java管理冲突。

我的问题是,如果生成的哈希码与ArrayList 中的相同,java不允许管理HashSet 或HashSet ,并且只需调用Arrays.hashCode即可计算数组的哈希码( …)。

最后,如果我想做一个HashSet (或HashSet ),我必须自己实现它? 或者有更好的方法吗?

谢谢。

更新:好的,最后我想我已经得到了一个完整的答案。 由于@ZiyaoWei和@ user1676075评论它不起作用,因为equals返回false而hashcode是不同的。 但是,为什么java不会覆盖这些方法(使用Arrays.equals(),Arrays.hashCode()),所以可以做一些像HashSet 这样的事情? 答案是因为数组是一个可变对象,并且根据哈希码的一般契约,哈希码不能依赖于可变值(数组的每个元素是一个可变值)。 可变对象和hashCode

这里有很好的解释,在hashCode中使用可变字段http://blog.mgm-tp.com/2012/03/hashset-java-puzzler/和hashmaps中的可变键是可变的hashmap键是一种危险的做法吗?

我的答案是,如果你想使用HashSet ,你必须创建一个具有数组的类,如果你想要那个hashcode和equals依赖于值,重写方法equals()和hashCode()与数组.equals()和Arrays.hashCode()。 如果你不想违反合同,只需让arrays最终。

感谢大家!

它与一天结束时的碰撞无关:

 a1.equals(a2) == false 

由于它们不相等,因此Set会将它们视为不同。

注意Java中的Array不会覆盖Objectequals方法。

并且因为add Set定义为

更正式地,如果集合不包含元素e2,则将指定的元素e添加到此集合中(e == null?e2 == null:e.equals(e2))

似乎无法正确实现可能符合您的要求的Set (与Arrays.equals比较元素)而不违反某些合同。

HashSet>工作的原因是因为HashSet将使用.equals()比较来决定是否要插入相同的对象两次。 在List的情况下,具有相同内容的两个具有相同基本类型的列表(例如,ArrayList)将以相同的顺序进行比较。 因此,您告诉HashSet两次插入相同的对象。 它只需要一次实例。

当您尝试使用数组执行相同的操作时。 有关Java中数组比较的更多详细信息,请参阅以下文章: Java中的equals vs Arrays.equals 。 当您插入两个数组时,默认的.equals()测试它们是否是同一个对象,它们不是。 因此它失败了。