檢查一個列表是否包含來自Java中另一個列表的元素
一、概述
在本教程中,我們將了解 Java 中的幾種方法,用於檢查一個List
中的元素是否也存在於另一個.我們將探討如何使用 Java Stream
s、 Collection
s disjoint()
和 Apache Commons 實現它的各種方法。
2. 檢查基本等價性
此問題的最簡單版本是,如果我們要檢查一個List
中的元素是否等同於另一個 List中的元素。這可能是原始值或對象,假設我們已經設置了要比較的對象。讓我們創建一些List
來比較:
List<String> listOfLetters = Arrays.asList("a", "b", "c", "d");
List<String> listOfLettersWithOverlap = Arrays.asList("d", "e", "f", "g");
List<String> listOfCities = Arrays.asList("London", "Berlin", "Paris", "Brussels");
String
“d”出現在前兩個List
中,因此我們希望解決此問題的任何解決方案都能檢測到這一點。我們還希望將前兩個中的任何一個與listOfCities
進行比較會返回否定結果。
2.1.使用不相交
我們要看的第一個選項是 Java Collection
庫中的disjoint()
方法。如果兩個指定的Collection
沒有共同的元素,則disjoint()
返回 true 。因此,當我們要查找兩個Collection
何時do
具有共同元素時,我們將使用 not 運算符反轉結果:
@Test
void givenValuesToCompare_whenUsingCollectionsDisjoint_thenDetectElementsInTwoLists() {
boolean shouldBeTrue = !Collections.disjoint(listOfLetters, listOfLettersWithOverlap);
assertTrue(shouldBeTrue);
boolean shouldBeFalse = !Collections.disjoint(listOfLetters, listOfCities);
assertFalse(shouldBeFalse);
}
在上方,我們看到重疊的字母列表在與城市列表進行比較後返回true
和false
值的預期結果。
2.2.使用流
我們在 Java 中可用的第二種方法是使用Stream
s。具體來說,我們將使用anyMatch()
方法,如果Stream
中的任何元素與給定的謂詞匹配,該方法將返回 true:
@Test
void givenValuesToCompare_whenUsingStreams_thenDetectElementsInTwoLists() {
boolean shouldBeTrue = listOfLetters.stream()
.anyMatch(listOfLettersWithOverlap::contains);
assertTrue(shouldBeTrue);
boolean shouldBeFalse = listOfLetters.stream()
.anyMatch(listOfCities::contains);
assertFalse(shouldBeFalse);
}
提供給anyMatch()
謂詞是對Collection
的contains()
方法的調用。如果Collection
包含指定的元素,則返回true
。
2.3.使用 Apache Commons
我們的最終方法是使用 Apache Commons CollectionUtils
方法containsAny()
。為了使用它,我們首先需要將依賴項導入到我們的pom.xml
中:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
我們可以在Maven Repository中找到最新版本。準備就緒後,我們就可以像這樣使用庫了:
void givenValuesToCompare_whenUsingApacheCollectionUtils_thenDetectElementsInTwoLists() {
boolean shouldBeTrue = CollectionUtils.containsAny(listOfLetters, listOfLettersWithOverlap);
assertTrue(shouldBeTrue);
boolean shouldBeFalse = CollectionUtils.containsAny(listOfLetters, listOfCities);
assertFalse(shouldBeFalse);
}
這種方法簡單易讀。但是,只有在我們已經在使用 Apache 導入時才可能使用它,因為有內置的 Java 方法。
3. 檢查對像中的屬性
這個問題的一個更複雜的版本是,如果我們想檢查兩個List
中的任何對像是否具有匹配的屬性。讓我們創建一個示例對象,我們可以使用它:
class Country {
String name;
String language;
// standard getters, setters and constructors
}
之後,我們可以創建Country
類的幾個實例並將它們放入兩個List
中:
Country france = new Country("France", "French");
Country mexico = new Country("Mexico", "Spanish");
Country spain = new Country("Spain", "Spanish");
List<Country> franceAndMexico = Arrays.asList(france, mexico);
List<Country> franceAndSpain = Arrays.asList(france, spain);
兩個List
都有一個使用西班牙語的國家/地區,因此我們應該能夠在比較它們時檢測到這一點。
3.1.使用流
讓我們使用上面的List
並檢查我們是否有使用相同語言的國家。我們可以使用Stream
以類似於我們在 2.2 節中看到的方式來執行此操作。這裡的主要區別是我們使用map()
來提取我們感興趣的屬性,本例中的語言:
@Test
public void givenPropertiesInObjectsToCompare_whenUsingStreams_thenDetectElementsInTwoLists() {
boolean shouldBeTrue = franceAndMexico.stream()
.map(Country::getLanguage)
.anyMatch(franceAndSpain.stream()
.map(Country::getLanguage)
.collect(toSet())::contains);
assertTrue(shouldBeTrue);
}
我們再次使用anyMatch().
然而,這次我們將語言收集到一個Set
中,並使用contains()
來檢查當前語言是否在Set.
如上所示,我們找到一個匹配項,因為兩個List
都包含一個講西班牙語的國家/地區。
4。結論
在本文中,我們已經看到Stream
是解決此問題的最通用的解決方案。我們可以很容易地使用它們來比較整個對像或對像中的屬性。此外,我們還研究了使用 Java 的disjoint()
和 Apache 的containsAny()
的更簡單用例的替代方案。兩者都易於使用並生成可讀代碼。
與往常一樣,示例的完整代碼可在 GitHub 上獲得。