无论顺序如何,比较两个List <e>

时间:2015-07-14 13:17:15

标签: java list

我有两个E类型列表List list1,List list2。 E对象是一个POJO类,包含一行以下数据。两个列表都包含相同的数据。例如,在最后一列,如果我将false更改为true,则无法检测到。

| statusId  | statusName                                | statusState | isRequire            |
| 3         | Approved                                  | APPROVED    | false                |
| 201       | Attributed                                | REJECTED    | true                 |
| 202       | Denied                                    | REJECTED    | false                |
| 204       | Fraud                                     | REJECTED    | false                |
| 205       | Insufficient                              | REJECTED    | false                |
| 206       | Invalid                                   | REJECTED    | false                |
| 207       | Cancelled                                 | REJECTED    | false                |
| 208       | Cannot traced                             | REJECTED    | false                |
| 209       | Transaction online                        | REJECTED    | false                |
| 210       | Voucher                                   | REJECTED    | false                |
| 211       | does not meet req                         | REJECTED    | false                |

我想写一个函数,这样如果数据是那两个列表不同,那么就可以检测到它。以下是我的代码,但似乎总是给出“假”,两个列表中的数据是相同还是不同。

   private boolean compareLists(List<Status> actualStatuses, List<Status> expectedStatuses) {
    boolean indicator = false;
    if (actualStatuses!= null && expectedStatuses!=null && actualStatuses.size() == expectedStatuses.size()){
        for (Status expectedStatusData : expectedStatuses){
            for(Status actualStatusData : actualStatuses){
                if(actualStatusData.getStatusId() == expectedStatusData.getStatusId()
                        && actualStatusData.getStatusName().equals(expectedStatusData.getStatusName())
                        && actualStatusData.getStatusState().equals(expectedStatusData.getStatusState())
                        && actualStatusData.isEnable() == expectedStatusData.isEnable()
                        && actualClaimStatusData.isRequire() == expectedStatusData.isRequire()){
                    indicator = true;
                    break;
                }
                else indicator = false;
            }
        }
        if (indicator)
            return true;
    }
    else
        return false;

    return indicator;
}

4 个答案:

答案 0 :(得分:5)

更好的方法(假设列表不包含重复值)是将一个列表的所有元素存储在HashSet中,然后检查HashSet是否包含所有元素另一个列表的元素和它们的大小是相同的。

private <E> boolean listsHaveSameElements(final List<E> l1, final List<E> l2) {
    final Set<E> set = new HashSet<>(l1);
    return l1.size() == l2.size() && set.containsAll(l2);
}

这是O(n+m)解决方案,而使用List.containsAll()需要迭代其他列表的所有元素以检查是否存在,因此它将是O(n*m)

答案 1 :(得分:1)

基本上,如果大小相等,您可以迭代两个列表,当您在expectedStatuses中找不到actualStatuses中找不到的第一个状态时,您可以返回false,因为列表不是等于了。

但是,如果列表变大,您可能会遇到性能问题,因为这基本上是O(n 2 )方法。在这种情况下,您可以先将所有预期的状态放入一个集合中,然后删除实际的状态。如果最后该集合不为空,则列表不相等,您甚至不知道缺少哪些状态。如果您只需要检查是否相等,只需检查该集是否包含第二个列表的元素。在最坏的情况下,两者都是O(n)。

注意List.containsAll()与上面描述的基本相同,即遍历集合参数,并且每个元素在其自己的列表中查找(调用contains(e))并且在找不到的第一个元素上返回false

编辑:

如果您的元素已正确实施List.containsAll()hashCode(),则使用集合与equals()同样简单:

new HashSet<Status>( expectedStatuses ).containsAll( actualStatuses );

答案 2 :(得分:0)

怎么样:

private boolean compareLists(List<Status> actualStatuses, List<Status> expectedStatuses) {
    boolean listsHaveSameSize = actualStatuses.size() == expectedStatuses.size();

    return listsHaveSameSize ? actualStatuses.containsAll(expectedStatuses)
                             : false;
}

答案 3 :(得分:0)

public <T> boolean equalsIgnoreOrder(List<T> list1, List<T> list2) {
    if (list1.size() != list2.size()) {
       return false;
    }
    Map<T, Integer> map1 = createCountMap(list1);
    Map<T, Integer> map2 = createCountMap(list2);
    return map1.equals(map2);
}

/**
 * Note that T must have a proper hashCode() and equals() for this to work
 */
private <T> Map<T, Integer> createCountMap(List<T> list) {
    Map<T, Integer> map = new HashMap<T, Integer>();
    for (T value : list) {
        Integer prevCount = map.get(value);
        map.put(value, prevCount == null ? 1 : prevCount + 1);
    }
    return map;
}