查找Java中兩個列表之間的差異
1.概述
在相同數據類型的對象集合之間找到差異是一項常見的編程任務。例如,假設我們有一個申請考試的學生列表和另一個通過考試的學生列表。這兩個列表之間的差異將為我們提供未通過考試的學生。
在Java
,儘管有一些輔助方法很接近,但是在List
API中沒有明確的方法可以找到兩個列表之間的差異。
在本快速教程中,我們將研究如何找到兩個列表之間的差異。我們將嘗試幾種不同的方法,包括純Java
(帶有和不帶有Streams
Java
)以及使用第三方庫(例如Guava
和Apache Commons Collections
。
2.編寫測試用例
讓我們從定義兩個列表開始,我們將使用它們來測試示例:
public class FindDifferencesBetweenListsUnitTest {
private static final List listOne = Arrays.asList("Jack", "Tom", "Sam", "John", "James", "Jack");
private static final List listTwo = Arrays.asList("Jack", "Daniel", "Sam", "Alan", "James", "George");
}
3.使用Java List
API
我們可以創建一個列表的副本,然後使用List
方法removeAll()
刪除與另一個列表相同的所有元素:
List<String> differences = new ArrayList<>(listOne);
differences.removeAll(listTwo);
assertEquals(2, differences.size());
assertThat(differences).containsExactly("Tom", "John");
讓我們反向進行相反的查找差異:
List<String> differences = new ArrayList<>(listTwo);
differences.removeAll(listOne);
assertEquals(3, differences.size());
assertThat(differences).containsExactly("Daniel", "Alan", "George");
我們還應注意,如果要查找兩個列表之間的公共元素,則List
還包含一個retainAll
方法。
4.使用Streams API
Java Stream
可用於對集合中的數據執行順序操作,包括過濾列表之間的差異:
List<String> differences = listOne.stream()
.filter(element -> !listTwo.contains(element))
.collect(Collectors.toList());
assertEquals(2, differences.size());
assertThat(differences).containsExactly("Tom", "John");
與第一個示例一樣,我們可以切換列表的順序以從第二個列表中查找不同的元素:
List<String> differences = listTwo.stream()
.filter(element -> !listOne.contains(element))
.collect(Collectors.toList());
assertEquals(3, differences.size());
assertThat(differences).containsExactly("Daniel", "Alan", "George");
我們應該注意List
的反複調用。對於較大的列表, contains()
可能是一項昂貴的操作。
5.使用第三方庫
5.1。使用谷歌Guava
Guava
包含一個方便的Sets
。 difference
方法,但是要使用它,我們需要先將List
轉換為Set
:
List<String> differences = new ArrayList<>(Sets.difference(Sets.newHashSet(listOne), Sets.newHashSet(listTwo)));
assertEquals(2, differences.size());
assertThat(differences).containsExactlyInAnyOrder("Tom", "John");
我們應該注意,將List
轉換為Set
將具有重複數據刪除和重新排序的效果。
5.2。使用Apache Commons集合
Apache Commons Collections
中的CollectionUtils
類包含removeAll
方法。
此方法與List
相同。 removeAll
,同時還為結果創建一個新集合:
List<String> differences = new ArrayList<>((CollectionUtils.removeAll(listOne, listTwo)));
assertEquals(2, differences.size());
assertThat(differences).containsExactly("Tom", "John");
6.處理重複值
現在讓我們看一下兩個列表包含重複值時的差異。
為此,我們需要從第一個列表中刪除重複的元素,精確的次數應與第二個列表中包含它們的次數相同。
在我們的示例中,值“Jack”
在第一個列表中出現兩次,而在第二個列表中僅出現一次:
List<String> differences = new ArrayList<>(listOne);
listTwo.forEach(differences::remove);
assertThat(differences).containsExactly("Tom", "John", "Jack");
我們還可以使用Apache Commons Collections
的subtract
方法實現此目的:
List<String> differences = new ArrayList<>(CollectionUtils.subtract(listOne, listTwo));
assertEquals(3, differences.size());
assertThat(differences).containsExactly("Tom", "John", "Jack");
7.結論
在本文中,我們探索了幾種查找列表之間差異的方法。
在示例中,我們介紹了基本的Java解決方案,
使用Streams
API以及第三方庫(例如Google Guava
和Apache Commons Collections.
我們還看到瞭如何處理重複值。
與往常一樣,完整的源代碼可以在GitHub上找到。