我如何检查两个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))两个元素e1e2是相等的。)换句话说,如果两个列表包含相同元素的顺序相同。 此定义确保了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.equalsList.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 ,然后在containsremoveAll调用的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