JAVA/Stream

[Java] Stream > findAny, findFirst

앵낄낄 2023. 7. 4. 19:24
반응형

git

https://github.com/ymwoo88/stream/tree/feature/find%EA%B8%B0%EB%8A%A5-%EC%98%88%EC%A0%9C

설명

findFirst

  • Stream 안의 첫번째 데이터를 반환합니다.
  • Stream이 비어있다면 빈 Optional을 반환합니다.
이 스트림의 첫 번째 요소를 설명하는 옵션을 반환하거나 스트림이 비어 있으면 빈 옵션을 반환합니다. 
스트림에 발생 순서가 없으면 모든 요소가 반환될 수 있습니다.
이것은 단락 단자 작동입니다.

Returns: 이 스트림의 첫 번째 요소를 설명하는 Optional 또는 스트림이 비어 있는 경우 빈 Optional
Throws: NullPointerException – 선택한 요소가 null인 경우

Optional<T> findFirst();

findAny

  • Stream 안의 아무 데이터나 리턴합니다.(매번 달라지기 때문에 순서가 필요 없을 때 사용합니다.
  • Parallel Stream을 사용할 때 최적화를 할 수 있습니다.
  • Stream이 비어있다면 빈 Optional을 반환합니다.
스트림의 일부 요소를 설명하는 옵션을 반환하거나 스트림이 비어 있으면 빈 옵션을 반환합니다.
이것은 단락 단자 작동입니다.
이 작업의 동작은 명시적으로 비결정적입니다. 
스트림의 모든 요소를 자유롭게 선택할 수 있습니다. 이는 병렬 작업에서 최대 성능을 허용하기 위한 것입니다. 
비용은 동일한 소스에 대한 여러 호출이 동일한 결과를 반환하지 않을 수 있다는 것입니다. 
(안정적인 결과를 원하면 대신 findFirst()를 사용하십시오.)

Returns: 이 스트림의 일부 요소를 설명하는 Optional 또는 스트림이 비어 있는 경우 빈 Optional
Throws: NullPointerException – 선택한 요소가 null인 경우
See Also : findFirst()

Optional<T> findAny();

예제

  • 샘플 데이터
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private Long id;
    private String name;
    private String email;
    private Integer age;
    private Boolean isWorking;
    private List<String> hobbies;


    public static User getUserAmil() {
        return User.builder()
                .id(1L)
                .name("amil")
                .email("amil@ymwoo.com")
                .age(28)
                .isWorking(true)
                .hobbies(List.of("골프", "영화감상"))
                .build();
    }

    public static User getUserBenny() {
        return User.builder()
                .id(2L)
                .name("benny")
                .email("benny@ymwoo.com")
                .age(26)
                .isWorking(true)
                .hobbies(List.of("골프", "낚시"))
                .build();
    }

    public static User getUserCho() {
        return User.builder()
                .id(3L)
                .name("cho")
                .email("cho@ymwoo.com")
                .age(33)
                .isWorking(false)
                .hobbies(List.of("등산", "캥핌"))
                .build();
    }

    public static List<User> getExamUserList() {
        return Arrays.asList(getUserAmil(), getUserCho(), getUserBenny());
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof User) {
            return this.isWorking.equals(((User) o).getIsWorking());   // 값 비교
        }
        return false;
    }

    @Override
    public int hashCode() {
        return isWorking.hashCode();
    }
}
  • 예졔1) Stream findAny, findFirst
@Test
@DisplayName("Stream findAny, findFirst 테스트")
void case1() {
    List<User> examUserList = User.getExamUserList();

    Optional<User> first = examUserList.stream()
            .filter(User::getIsWorking)
            .findFirst(); // return 이 Optional

    List<User> isWorkingUserList = examUserList.stream()
            .filter(User::getIsWorking).toList();
    // 2개 이상 검증
    Assertions.assertEquals(2, isWorkingUserList.size());
    // 2개 중에 any 뭐가 나올까..?
    Optional<User> any = isWorkingUserList.stream()
            .filter(User::getIsWorking)
            .findAny(); // return 이 Optional

    // 확인
    log.info("findFirst = {}", first.get());
    // any 결과를 보니까 first와 다를게 없어보이네.. 무조건 앞에께 튀나오네
    log.info("findAny = {}", any.get());
}
19:08:49.333 [Test worker] INFO com.ymwoo.stream.first.StreamFirstSeriesTest -- findFirst = User(id=1, name=amil, email=amil@ymwoo.com, age=28, isWorking=true, hobbies=[골프, 영화감상])
19:08:49.341 [Test worker] INFO com.ymwoo.stream.first.StreamFirstSeriesTest -- findAny = User(id=1, name=amil, email=amil@ymwoo.com, age=28, isWorking=true, hobbies=[골프, 영화감상])

근데.. 
findAny의 경우 동일한 소스에 대한 여러 호출이 동일한 결과를 반환하지 않을 수 있다고하는데
예시가 3개 뿐이긴했지만 항상 같은 결과가 나오는 상황을 맞이했다.. 
아마도 적은 수의 데이터일 경우 성능상 맨 처음에 우선적으로 나오는 듯 하다.. 

참조

https://backtony.github.io/java/2022-02-06-java-46/

반응형