如何检查两个ArrayList是否不同,我不在乎改变了什么

问题描述 投票:37回答:6

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

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

现在,ArrayList的值实际上是我创建的一个类(包含name,lvl,rank,score)。

我需要在它上面实施equals()吗?

java arraylist
6个回答
8
投票

这是一个简单的方法,可以检查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;
    }

79
投票

On the definition of "sameness"

正如约阿希姆所指出的,对于大多数应用,List.equals(Object o)定义有效:

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

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

    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"

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

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

您还提到该列表必须包含具有相同类型的元素。这是另一个元素不具有相同类型的例子,但它们是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应该足够了。


On implementing equals

更新后的信息表明List.equals可以正常工作,只要元素正确实现equals(因为List<E>.equals根据上面的API文档在非E.equals元素上调用null)。

所以在这种情况下,如果我们有一个List<Player>,那么Player必须@Override equals(Object o)返回true如果o instanceof Player和相关领域,他们都是equals(参考类型)或==(原始)。

当然,当你@Override equals,你也应该@Override int hashCode()。几乎不可接受的最低限度是return 42;;更好的是return name.hashCode();;最好是使用涉及您定义equals的所有字段的公式。一个好的IDE可以自动生成equals/hashCode方法。

See also

  • 有效的Java第二版 第8项:在超越平等时遵守总合同 第9项:覆盖equals时始终覆盖hashcode

API links

Related questions

equals/hashCode组合:

equals vs ==


11
投票

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

除非您想忽略值的顺序,否则您应该将值转储到两个Set对象中,并使用equals()进行比较。


2
投票

正如@Joachim Sauer在他的回答中提到的,如果列表相等且其内容正确地实现等于,则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;
            }
        }

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

    //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中,因此性能较差。

我的名单保证很短,所以我不介意打击。


2
投票

你可以将它们转换为字符串然后进行比较

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

-1
投票

您还可以查看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);
}

感谢@Jacob

© www.soinside.com 2019 - 2024. All rights reserved.