Java 如何检查两个 ArrayList 是否不同,我不在乎发生了什么变化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2989987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:19:16  来源:igfitidea点击:

How can I check if two ArrayList differ, I don't care what's changed

javaarraylist

提问by ufk

How can I check if two ArrayLists differ from one another? I don't care what's the difference, I just want to know if they're not the same.

如何检查两个 ArrayList 是否彼此不同?我不在乎有什么区别,我只想知道它们是否不一样。

I'm fetching scores list from a database every minute, and only if the scores list that I fetched is different from the one I fetched a minute ago I want to send it to the client.

我每分钟都从数据库中获取分数列表,并且只有当我获取的分数列表与我一分钟前获取的分数列表不同时,我才想将其发送给客户端。

Now the value of the ArrayList is actually a class that I created (that contains name, lvl, rank, score).

现在 ArrayList 的值实际上是我创建的一个类(包含名称、等级、等级、分数)。

Do I need to implement equals()on it?

我需要实施equals()吗?

采纳答案by Traveling Salesman

Here's a simple method that checks if 2 Array Lists contain the same values regardless their order.

这是一个简单的方法,用于检查 2 个数组列表是否包含相同的值,而不管它们的顺序。

 //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;
    }

回答by Joachim Sauer

Use equals(). As long as the elements inside the lists implement equals()correctly it will return the correct values.

使用equals(). 只要列表中的元素equals()正确实现,它就会返回正确的值。

Unless you want to ignore the order of the values, then you should dump the values in two Setobjects and compare those using equals().

除非您想忽略值的顺序,否则您应该转储两个Set对象中的值并使用equals().

回答by polygenelubricants

On the definition of "sameness"

关于“相同”的定义

As Joachim noted, for most application, List.equals(Object o)definition works:

正如 Joachim 所指出的,对于大多数应用程序,List.equals(Object o)定义是有效的:

Compares the specified object with this list for equality. Returns trueif and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1and e2are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equalsmethod works properly across different implementations of the Listinterface.

比较指定的对象与此列表是否相等。返回true当且仅当该指定的对象也是一个列表,两个列表具有相同的大小,并且在两个列表元素的所有相应的对是相等的。(两个元素e1e2如果,则相等(e1==null ? e2==null : e1.equals(e2))。)换句话说,如果两个列表以相同的顺序包含相同的元素,则它们被定义为相等。此定义可确保该equals方法在List接口的不同实现中正常工作。

Depending on how you're using it, though, this may not work as expected. If you have a List<int[]>, for example, it doesn't quite work because arrays inherit equalsfrom Objectwhich defines equality as reference identity.

但是,根据您使用它的方式,这可能无法按预期工作。List<int[]>例如,如果您有一个,它就不太适用,因为数组继承equalsObject它定义了相等性作为引用标识。

    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"

Also, two lists with different type parameter can be equals:

此外,具有不同类型参数的两个列表可以是equals

    List<Number> list1 = new ArrayList<Number>();
    List<String> list2 = new ArrayList<String>();
    System.out.println(list1.equals(list2)); // prints "true"

You also mentioned that the list must contain elements with the same type. Here's yet another example where the elements don't have the same type, and yet they're equals:

您还提到列表必须包含相同类型的元素。这是另一个示例,其中元素没有相同的类型,但它们是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"

So unless you clearly define what equality means to you, the question can have very different answers. For most practical purposes, though, List.equalsshould suffice.

所以除非你清楚地定义平等对你意味着什么,否则这个问题可能会有非常不同的答案。不过,对于大多数实际目的来说,List.equals应该足够了。



On implementing equals

关于实施 equals

Information after update suggests that List.equalswill do the job just fine, providedthat the elements implement equalsproperly (because List<E>.equalsinvokes E.equalson the non-null-elements, per the API documentation above).

更新后的信息表明List.equals只要元素equals正确实现,就可以很好地完成工作(因为根据上面的 API 文档对非元素进行List<E>.equals调用)。E.equalsnull

So in this case, if we have, say, a List<Player>, then Playermust @Override equals(Object o)to return trueif o instanceof Playerand on the relevant fields, they're all equals(for reference types) or ==(for primitives).

所以在这种情况下,如果我们有,比如说, a List<Player>,那么Player必须@Override equals(Object o)返回trueifo instanceof Player和 on 相关字段,它们都是equals(对于引用类型)或==(对于基元)。

Of course, when you @Override equals, you should also @Override int hashCode(). The barely acceptable minimum is to return 42;; slightly better is to return name.hashCode();; best is to use a formula that involves all the fields on which you define equals. A good IDE can automatically generate equals/hashCodemethods for you.

当然,当你 时@Override equals,你也应该@Override int hashCode()。勉强可以接受的最小值是return 42;;稍微好一点的是return name.hashCode();;最好的方法是使用一个包含您定义的所有字段的公式equals。一个好的 IDE 可以自动equals/hashCode为你生成方法。

See also

也可以看看

  • Effective Java 2nd Edition
    • Item 8: Obey the general contract when overriding equals
    • Item 9: Always override hashcode when you override equals
  • 有效的 Java 第二版
    • 第 8 条:在覆盖 equals 时遵守一般约定
    • 第 9 条:在覆盖 equals 时始终覆盖哈希码

API links

接口链接

Related questions

相关问题

On equals/hashCodecombo:

equals/hashCode组合:

On equalsvs ==:

equalsVS ==

回答by Aristo Michael

You can also check the Arraylist as shown below:

您还可以检查 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 A. R. S.
one = new ArrayList<String>(one); 
two = new ArrayList<String>(two);   

Collections.sort(one);
Collections.sort(two);      
return one.equals(two);
}

Thanks to @Jacob

感谢@Jacob

回答by frostymarvelous

As @Joachim Sauer mentioned in his answer, equals should work if the lists are equal and their contents implement equals correctly. But, it shouldn't work if the items are not in the same "order" since it doesn't use contains for the check. In this sense, it checks for "strict" equality as mentioned by @jarnbjo

正如@Joachim Sauer 在他的回答中提到的,如果列表相等并且它们的内容正确实现 equals,那么 equals 应该可以工作。但是,如果项目不在相同的“顺序”中,它应该不起作用,因为它不使用包含进行检查。从这个意义上说,它检查@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;
            }
        }

However, I wanted somewhat different behaviour, I didn't care about order or anything like that. All I wanted was to be sure the two didn't contain the same items. My solution,

但是,我想要一些不同的行为,我不在乎订单或类似的东西。我想要的只是确保两者不包含相同的项目。我的解决方案,

    //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

This is less performant since it loops twice, first in removeAlland then in containswhich is called by removeAll.

这性能较差,因为它循环了两次,首先是 in removeAll,然后是 in containswhich 被调用removeAll

My list was guaranteed to be short so I didn't mind the hit.

我的名单肯定很短,所以我不介意受到打击。

回答by Robert Londo

You can convert them to string and then compare like

您可以将它们转换为字符串,然后比较

list1.toString().equals(list2.toString())