findFirst() và findAny() trong Stream Java 8

Người dịch : Nguyễn Minh Tuấn
Email liên hệ : tuann.nm241@gmail.com
Bài viết gốc : https://www.baeldung.com/java-stream-findfirst-vs-findany

1. Tổng quan

Trong Stream API Java 8 có 2 phương thức dễ gây nhầm lẫn đó là : findAny() và findFirst().
Trong bài này, chúng ta cùng tìm hiểu sự khác nhau giữa 2 phương thức trên.

2. Sử dụng Stream.findAny()

Đúng như tên gọi , phương tức findAny() cho phép chúng ta tìm bất kể phần tử nào của Stream.
Chúng ta sử dụng phương thức này khi chúng ta không quan tâm đến thứ tự của kết quả.
Phương thức này trả về Optional , kết quả sẽ rỗng nếu Stream rỗng.

@Test
public void createStream_whenFindAnyResultIsPresent_thenCorrect() {
    List<String> list = Arrays.asList("A","B","C","D");

    Optional<String> result = list.stream().findAny();

    assertTrue(result.isPresent());
    assertThat(result.get(), anyOf(is("A"), is("B"), is("C"), is("D")));
}

Nếu không sử dụng xử lý song song , rất có thể findAny() sẽ trả về phần tử đầu tiên của Stream.
Để tăng tốc về hiệu năng, khi sử dụng xử lý song song thì kết quả sẽ không được xác định một cách cụ thể.

    @Test
    public void createParallelStream_whenFindAnyResultIsPresent_thenCorrect() throws Exception {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        Optional<Integer> result = list.stream().parallel().filter(num -> num < 4).findAny();

        assertTrue(result.isPresent());
        assertThat(result.get(), anyOf(is(1), is(2), is(3)));
    }

3. Sử dụng Stream.findFirst()

Phương thức findFirst() sẽ tìm ra phần tử đầu tiên của Stream . Vì thế chúng ta sử dụng phương thức này khi quan tâm về phần tử đầu tiên của chuỗi tuần tự.
Khi không được định nghĩa thứ tự, findFirst() có thể trả về bất kể phần tử nào của Stream.
Theo như tài liệu từ java.util.streams package : “Streams may or may not have a defined encounter order. It depends on the source and the intermediate operations.” có thể hiểu là :
Streams có thể hoặc không thể định nghĩa thứ tự phần tử , điều này phụ thuộc vào tài nguyên và các hoạt động trung gian.
Cũng giống như findAny() , kiểu trả về của findFirst() là một Optional instance và nó sẽ rỗng nếu như Stream rỗng.

@Test
public void createStream_whenFindFirstResultIsPresent_thenCorrect() {

    List<String> list = Arrays.asList("A", "B", "C", "D");

    Optional<String> result = list.stream().findFirst();

    assertTrue(result.isPresent());
    assertThat(result.get(), is("A"));
}

Cách hoạt động của phương thức findFirst sẽ không thay đổi kể cả khi sử dụng xử lý song song. Nếu Stream được xác định thứ tự , thì sẽ luôn xác định chính xác kết quả của findFirst() trả về.

4. Kết luận

Trong bài này, chúng ta đã tìm hiểu về phương thức findAny() và findFirst() của Stream API trong Java 8.
Phương thức findAny() trả về bất kể phần tử nào từ Stream, trong khi đó phương thức findFirst() trả về phần tử đầu tiên của Stream.