查找Java中兩個列表之間的差異

1.概述

在相同數據類型的對象集合之間找到差異是一項常見的編程任務。例如,假設我們有一個申請考試的學生列表和另一個通過考試的學生列表。這兩個列表之間的差異將為我們提供未通過考試的學生。

Java ,儘管有一些輔助方法很接近,但是在List API中沒有明確的方法可以找到兩個列表之間的差異。

在本快速教程中,我們將研究如何找到兩個列表之間的差異。我們將嘗試幾種不同的方法,包括純Java (帶有和不帶有Streams Java )以及使用第三方庫(例如GuavaApache 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包含一個方便的Setsdifference方法,但是要使用它,我們需要先將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 Collectionssubtract方法實現此目的:

List<String> differences = new ArrayList<>(CollectionUtils.subtract(listOne, listTwo));

 assertEquals(3, differences.size());

 assertThat(differences).containsExactly("Tom", "John", "Jack");

7.結論

在本文中,我們探索了幾種查找列表之間差異的方法

在示例中,我們介紹了基本的Java解決方案,使用Streams API以及第三方庫(例如Google GuavaApache Commons Collections.

我們還看到瞭如何處理重複值。

與往常一樣,完整的源代碼可以在GitHub上找到