天天看點

判斷兩個List是否相等

最近一位同學在面試時被問到如何比較兩個list是否相等?Java中的list是按自然順序排列的。是以,如果兩個list包含相同順序的完全相同的元素,則認為它們是相等的,如果忽略元素順序怎麼樣去比較兩個清單?

直接使用equals比較

衆所周知,兩個清單具有完全相同的元素并且具有完全相同的順序時,它們是相等的。是以, 如果我們業務要求兩個list順序一緻,可以使用equals()方法進行相等性檢查。

@Test
public void equalityCheckOfTwoLists() {
  
    List<Integer> list1 = Arrays.asList(1, 2, 3);
    List<Integer> list2 = Arrays.asList(1, 2, 3);
    List<Integer> list3 = Arrays.asList(2, 1, 3);
  
    assertTrue(list1.equals(list2));
    assertFalse(list1.equals(list3));
  
}      

即使list1的和項目list3包含相同的元素{1,2,3},但是元素順序不一樣,是以list1和list3還是不相等的。

注意: 有的業務元素的順序不必要求一緻,隻看兩個清單是否包含相同的元素,那如何去實作呢?

将list排序之後再比較

校驗邏輯主要有:

(1) 如果兩個list都為null,則傳回true

(2)如果一個list不為空 ,另外一個指向空值傳回false

(3)兩個list的size()不同 ,傳回false。

上面條件都不滿足,我們就把兩個list排序再進行比較:

public <T extends Comparable<T>> boolean isEquals(List<T> list1, List<T> list2){     
    if (list1 == null && list2 == null) {
        return true;
    }
    //Only one of them is null
    else if(list1 == null || list2 == null) {
        return false;
    }
    else if(list1.size() != list2.size()) {
        return false; 
    }
     
    //copying to avoid rearranging original lists
    list1 = new ArrayList<T>(list1); 
    list2 = new ArrayList<T>(list2);   
  
    Collections.sort(list1);
    Collections.sort(list2);      
     
    return list1.equals(list2);
}      

請注意:我們這裡建立了兩個清單的副本來保證原始清單中的元素保持不變。

使用Sets / contains()比較list

如果清單沒有重複元素 ,我們可以使用list中建立TreeSet,然後使用equals()比較。

public <T extends Comparable<T>> boolean isEquals(List<T> list1, List<T> list2){     
    if (list1 == null && list2 == null) {
        return true;
    }
    //Only one of them is null
    else if(list1 == null || list2 == null) {
        return false;
    }
    else if(list1.size() != list2.size()) {
        return false; 
    }
  
    Set<T> set1 = new TreeSet<>(list1);
    Set<T> set2 = new TreeSet<>(list2);
     
    return set1.equals(set2);
}      

我們甚至可以更加簡單使用contains()比較,不用建立Sets:

return list1.containsAll(list2) && list2.containsAll(list1);      

但是這裡要注意 如果我們list元素存在重複,使用contains()或者Sets比較就會有問題。看下面這個案例你就知道怎麼回事了。

List<Integer> list1 = Arrays.asList(1, 2, 3, 3);
List<Integer> list2 = Arrays.asList(3, 1, 2, 2);
  
// will return true, but actual value should be false
System.out.println(list1.isEquals(list2));      

在上面的示例中,list1包含一個2和兩個3,而list2包含兩個2和一個3,我們可以看到兩個list其實是不相等的,但是程式會錯誤地傳回true。是以使用這個方法時要確定list元素沒有重複的

使用Apache Commons工具類

List<Integer> list1 = Arrays.asList(1, 2, 3, 3);
List<Integer> list2 = Arrays.asList(3, 1, 3, 2);
  
System.out.println(CollectionUtils.isEqualCollection(list1, list2)); //true