最近一位同學在面試時被問到如何比較兩個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