了解 Streams 中的 findAny() 和 anyMatch()
1. 概述
在本教程中,我們將探討 Java 8 Streams 中的兩個關鍵方法: findAny()和anyMatch() 。兩種方法都有不同的用途,理解它們的差異對於編寫有效的Stream操作至關重要。分別了解這些方法後,我們將直接比較findAny()和anyMatch() 。這種比較將有助於闡明何時根據期望的結果使用每種方法。
我們將簡要介紹相關方法,例如findFirst() 、 count()和allMatch() 。這些方法在各種場景中補充了findAny()和anyMatch() ,我們將快速概述它們如何適應更廣泛的 Stream API。
2. 理解findAny()
我們可以使用findAny()方法從Stream檢索任何元素。當元素的順序無關緊要時,它特別有用,因為它被設計為傳回一個元素,而不保證會傳回哪個元素。這使得它成為並行流的絕佳選擇,在並行流中,效能可以優先於維護元素的順序。
此方法傳回一個Optional ,這表示它可以保存一個值,或者如果Stream不包含元素則為空。這很有用,因為它迫使我們處理空結果的可能性,鼓勵更安全的程式碼實踐。
讓我們來看一個簡單的例子來看看findAny()角色:
@Test
public void whenFilterStreamUsingFindAny_thenOK() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer result = numbers.stream()
.filter(n -> n % 2 == 0)
.findAny()
.orElse(null);
assertNotNull(result);
assertTrue(Arrays.asList(2, 4, 6, 8, 10).contains(result));
}
在像上面這樣的順序Stream中, findAny()行為與findFirst().它會傳回找到的第一個匹配項。然而, findAny()的真正優勢在於使用並行流時,它可以快速抓取任何匹配的元素,當順序不重要時可能會提高效能:
@Test
public void whenParallelStreamUsingFindAny_thenOK() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer result = numbers.parallelStream()
.filter(n -> n % 2 == 0)
.findAny()
.orElse(null);
assertNotNull(result);
assertTrue(Arrays.asList(2, 4, 6, 8, 10).contains(result));
}
透過使用並行Stream , findAny()可以利用並行性來提高效能,尤其是對於較大的資料集。
3. 理解anyMatch()
anyMatch()方法用於檢查Stream中的任何元素是否與給定謂詞相符。 anyMatch()傳回boolean, true ,如果沒有元素滿足則false 。當我們只需要檢查任何元素是否滿足條件而不檢索實際元素時,這是理想的選擇。
anyMatch()特別高效,因為它可以短路Stream操作。一旦找到匹配的元素,它就會停止處理Stream的其餘部分。如果沒有元素匹配,則該方法將評估整個Stream 。這種行為在處理大型資料集時非常有用,因為它不需要不必要地評估每個元素。
讓我們來看一個簡單的例子來看看anyMatch()角色:
@Test
public void whenFilterStreamUsingAnyMatch_thenOK() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
boolean result = numbers.stream()
.anyMatch(n -> n % 2 == 0);
assertTrue(result);
}
當我們想要快速檢查Stream中的任何元素是否符合條件時,此方法非常有用,除非必要,否則不需要處理整個Stream 。
4. findAny()和anyMatch()之間的比較
雖然findAny()和anyMatch()在處理流程時都很有用,但它們具有不同的目的並傳回不同類型的結果。
下表提供了兩種方法的並排比較:
| 特徵 | findAny() |
anyMatch() |
|---|---|---|
| 返回類型 | Optional<T> |
boolean |
| 使用案例 | 當我們需要取得一個元素而不關心順序時 | 當我們需要驗證至少一個元素是否符合時 |
| 短路 | 一旦找到匹配元素就停止處理 | 一旦找到匹配就停止處理 |
| 平行流 | 在並行流中高效。快速返回任意元素 | 透過檢查條件在平行流中高效工作 |
| 空安全 | 回傳一個Optional來處理元素的缺失 |
如果沒有找到符合的元素則傳回false |
5.相關方法: findFirst() 、 count() 、 allMatch()
除了findAny()和anyMatch()之外, Stream還提供其他有用的方法,例如findFirst() 、 count()和allMatch() ,這些方法在處理集合時具有不同的用途。
findFirst()方法傳回Stream的第一個元素,無論它是順序處理還是並行處理。當元素順序很重要時,它特別有用,因為它保證返回遇到順序中的第一個元素:
@Test
public void whenFilterStreamUsingFindFirst_thenOK() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer result = numbers.stream()
.filter(n -> n % 2 == 0)
.findFirst()
.orElse(null);
assertNotNull(result);
assertEquals(2, result);
}
count()方法傳回Stream中的元素總數:
@Test
public void whenCountingElementsInStream_thenOK() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long count = numbers.stream()
.filter(n -> n % 2 == 0)
.count();
assertEquals(5, count);
}
allMatch()方法檢查Stream中的所有元素是否滿足提供的謂詞。如果有一個元素不符合條件,則會傳回false 。一旦遇到不匹配的元素,該方法就會短路:
@Test
public void whenCheckingAllMatch_thenOK() {
List<Integer> numbers = Arrays.asList(2, 4, 6, 8, 10);
boolean allEven = numbers.stream()
.allMatch(n -> n % 2 == 0);
assertTrue(allEven);
}
這些方法在Stream處理中都有特定的用途,讓我們可以根據條件檢索、計數或驗證元素。
六、結論
在本文中,我們探討了findAny()和anyMatch()之間的差異,以及它們在使用串流時如何服務於不同的目的。
雖然findAny()幫助我們從Stream中檢索元素, anyMatch()非常適合檢查是否有任何元素滿足條件。我們也涉及了相關方法,例如findFirst() 、 count()和allMatch() ,它們在處理Streams時提供了額外的靈活性。
與往常一樣,原始碼可以在 GitHub 上取得。