voo*_*o14 8 java arrays arraylist hashset
我正在尝试创建一组int的数组,问题是如果我尝试这样做:
HashSet<int[]> s = new HashSet<int[]>();
int a1[] = {1,2,3};
int a2[] = {1,2,3};
s.add(a1);
s.add(a2)
System.out.println(s.size());
Run Code Online (Sandbox Code Playgroud)
然后s有两个对象,但应该只有一个.注意:如果它是HashSet <Integer []>则无关紧要.它只是不起作用.
现在,如果我尝试使用ArrayList <Integer>执行此操作,请执行以下操作:
HashSet<ArrayList<Integer>> s = new HashSet<ArrayList<Integer>>();
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
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());
Run Code Online (Sandbox Code Playgroud)
然后s有一个对象.
我虽然有办法避免第一个代码中的错误,并将每个数组的哈希码存储在一个哈希集中,如下所示:
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<Integer> s= new HashSet<Integer>();//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());
Run Code Online (Sandbox Code Playgroud)
它适用于第一种情况(1,2,3),但是在存在碰撞的情况下它不起作用,因此我将不得不管理碰撞.所以,我认为我正在做的是自己实现一个HashSet.
使用HashSet <ArrayList <Integer >>它可以很好地工作.我想在这种情况下java管理冲突.
我的问题是,如果生成的哈希码与ArrayList <Integer>中的相同,java不允许管理HashSet <int []>或HashSet <Integer []>,并且只需调用Arrays.hashCode即可计算数组的哈希码( ...).
最后,如果我想做一个HashSet <int []>(或HashSet <Integer []>),我必须自己实现它?或者有更好的方法吗?
谢谢.
更新: 好的,最后我想我已经得到了一个完整的答案.由于@ZiyaoWei和@ user1676075评论它不起作用,因为equals返回false而hashcode是不同的.但是,为什么java不会覆盖这些方法(使用Arrays.equals(),Arrays.hashCode()),所以可以做一些像HashSet <int []>这样的事情?答案是因为数组是一个可变对象,并且根据哈希码的一般契约,哈希码不能依赖于可变值(数组的每个元素都是可变值).可变对象和hashCode
这里有很好的解释,在hashCode中使用可变字段 http://blog.mgm-tp.com/2012/03/hashset-java-puzzler/ 和hashmaps中的可变键 是可变的hashmap键是一种危险的做法吗?
我的答案是,如果你想使用HashSet <int []>你必须创建一个有数组的类,如果你想要那个hashcode和equals依赖于值,重写方法equals()和hashCode()与数组.equals()和Arrays.hashCode().如果你不想违反合同,只需让阵列最终.
感谢大家!
它与一天结束时的碰撞无关:
a1.equals(a2) == false
Run Code Online (Sandbox Code Playgroud)
由于它们不相等,所以Set会将它们视为不同的.
ArrayJava中的注释不会覆盖该equals方法Object.
因为addin Set被定义为
更正式地,如果集合不包含元素e2,则将指定的元素e添加到此集合中(e == null?e2 == null:e.equals(e2))
似乎不可能在不违反某些合同的情况下正确实施可Set满足您要求(与元素比较Arrays.equals)的要求.