我如何检查两个ArrayList是否有所不同,我不在乎发生了什么变化
我如何检查两个ArrayLists是否彼此不同? 我不在乎有什么区别,我只是想知道他们是不是一样。
我每分钟从数据库中取得分数列表,只有当我提取的分数列表与我在一分钟之前提取的分数列表不同时,我才想把它发送给客户端。
现在,ArrayList的值实际上是一个我创build的类(包含name,lvl,rank,score)。
我需要实现equals()
吗?
下面是一个简单的方法,用来检查2个数组列表是否包含相同的值,而不pipe它们的顺序。
//the name of the method explains it well... public boolean isTwoArrayListsWithSameValues(ArrayList<Object> list1, ArrayList<Object> list2) { //null checking if(list1==null && list2==null) return true; if((list1 == null && list2 != null) || (list1 != null && list2 == null)) return false; if(list1.size()!=list2.size()) return false; for(Object itemList1: list1) { if(!list2.contains(itemList1)) return false; } return true; }
关于“同一性”的定义
正如Joachim指出的,对于大多数应用程序, List.equals(Object o)
定义起作用:
将指定的对象与此列表进行比较以获得相等性。 当且仅当指定的对象也是一个列表时,才返回
true
,两个列表具有相同的大小,并且两个列表中所有相应的元素对相等。 (如果(e1==null ? e2==null : e1.equals(e2))
两个元素e1
和e2
是相等的。)换句话说,如果两个列表包含相同元素的顺序相同。 此定义确保了equals
方法在List
接口的不同实现之间正常工作。
但是,根据您的使用方式,这可能无法按预期工作。 例如,如果你有一个List<int[]>
,那么它就不能工作,因为数组inheritance了Object
equals
,它定义了等于参考标识。
List<int[]> list1 = Arrays.asList(new int[] { 1, 2, 3 }); List<int[]> list2 = Arrays.asList(new int[] { 1, 2, 3 }); System.out.println(list1.equals(list2)); // prints "false"
而且,具有不同types参数的两个列表可以是equals
:
List<Number> list1 = new ArrayList<Number>(); List<String> list2 = new ArrayList<String>(); System.out.println(list1.equals(list2)); // prints "true"
您还提到,列表必须包含相同types的元素。 这里还有另一个例子,元素的types不一样,但它们是equals
:
List<Object> list1 = new ArrayList<Object>(); List<Object> list2 = new ArrayList<Object>(); list1.add(new ArrayList<Integer>()); list2.add(new LinkedList<String>()); System.out.println(list1.equals(list2)); // prints "true"
所以,除非你清楚地界定了什么平等对你来说,这个问题可以有非常不同的答案。 但是,对于大多数实际的目的, List.equals
就足够了。
实行equals
更新后的信息表明, 只要元素实现了正确的equals
(因为List<E>.equals
根据上面的API文档在非null
元素上调用E.equals
, List.equals
将会很好地完成这项工作。
所以在这种情况下,如果我们有一个List<Player>
,那么Player
必须@Override equals(Object o)
返回true
如果o instanceof Player
和相关的字段都是equals
(对于引用types)或==
(对于原语)。
当然,当你@Override equals
,你也应该@Override int hashCode()
。 勉强可以接受的最低限度是return 42;
; 稍微好一点就是return name.hashCode();
; 最好的办法是使用一个涉及你定义的所有领域的公式。 一个好的IDE可以为你自动生成equals/hashCode
方法。
也可以看看
- 有效的Java第二版
- 第8项:压倒一切时,服从总合同
- 第9项:当您覆盖等于时,总是覆盖哈希码
API链接
-
Object.equals(Object)
-
Object.hashCode()
-
java.lang.Comparable
– 在这里不需要,但另一个重要的Java API合约
相关问题
在equals/hashCode
组合:
- 在Java中重写equals和hashcode
- 为什么hashCode()和equals()存在
- 如何确保hashCode()与equals()是一致的?
equals
vs ==
:
- 等于和==之间的区别
- 为什么equals()方法,当我们有==运算符?
- Java String.equals与==
使用equals()
。 只要列表中的元素正确地实现了equals()
,它就会返回正确的值。
除非你想忽略这些值的顺序,否则你应该把这些值转储到两个Set
对象中,然后用equals()
来比较。
正如@Joachim Sauer在他的回答中所提到的,如果名单是平等的,并且其内容实现的方式是正确的,那么平等就应该起作用。 但是,如果项目不在相同的“顺序”,它不应该工作,因为它不使用包含检查。 从这个意义上说,它检查@jarnbjo提到的“严格”的平等
//From android's Arraylist implementation Iterator<?> it = that.iterator(); for (int i = 0; i < s; i++) { Object eThis = a[i]; Object eThat = it.next(); if (eThis == null ? eThat != null : !eThis.equals(eThat)) { return false; } }
但是,我想要有些不同的行为,我不关心秩序或类似的东西。 我想要的只是确定两者不包含相同的物品。 我的解决scheme
//first check that both are not null and are of same length. (not shown here) //if both match, pull out the big guns as below ... List<Object> comparedList = new ArrayList<>(listOne); comparedList.removeAll(listTwo); if(comparedList.size() != 0) //there are differences between the two
这是性能较差,因为它循环两次,首先在removeAll
,然后在contains
由removeAll
调用的contains
。
我的名单保证是短暂的,所以我不介意的打击。
您也可以检查Arraylist如下所示:
public boolean equalLists(List<String> one, List<String> two){ if (one == null && two == null){ return true; } if((one == null && two != null) || one != null && two == null || one.size() != two.size()){ return false; } //to avoid messing the order of the lists we will use a copy //as noted in comments by ARS one = new ArrayList<String>(one); two = new ArrayList<String>(two); Collections.sort(one); Collections.sort(two); return one.equals(two); }
感谢@Jacob