了解 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 上取得。