[java] Java 8에서 findAny ()와 findFirst ()의 차이점

Java 8 의 API Stream#findAny()와 API 간에 약간 혼동이 있습니다.Stream#findFirst()Stream

예를 들어 필터와 함께 사용할 때 둘 다 스트림에서 첫 번째로 일치하는 요소를 반환한다는 것을 이해했습니다.

그렇다면 동일한 작업에 대해 두 가지 방법이있는 이유는 무엇입니까? 내가 뭔가를 놓치고 있습니까?



답변

예를 들어 필터와 함께 사용할 때 둘 다 스트림에서 첫 번째로 일치하는 요소를 반환한다는 것을 이해했습니다.

그건 사실이 아니야. javadoc가에 따르면 Stream#findAny():

스트림의 일부 요소를 Optional<T>설명 하거나 스트림이 비어 있는 경우 비어
있는 것을 리턴합니다 . 이 작업의 동작은 명시 적으로 비 결정적입니다. 스트림의 모든 요소를 ​​자유롭게 선택할 수 있습니다. 이는 병렬 작업에서 최대 성능을 허용하기위한 것입니다.Optional<T>

while Stream.findFirst()은 스트림의 첫 번째 요소 Optional<T>엄격하게 설명 하는 것을 반환 합니다. Stream클래스는없는 .findOne()난 당신이 의미 가정, 그래서 방법을 .findFirst().


답변

아니요, 둘 다 Stream의 첫 번째 요소를 반환하지 않습니다.

출처 Stream.findAny()(강조 내) :

스트림의 일부 요소Optional설명 하거나 스트림이 비어 있는 경우 비어 있는 것을 리턴합니다 .Optional

이것은 단락 터미널 작동입니다.

이 작업의 동작은 명시 적으로 비 결정적입니다. 스트림의 모든 요소를 ​​자유롭게 선택할 수 있습니다. 이는 병렬 작업에서 최대 성능을 허용하기위한 것입니다. 비용은 동일한 소스에서 여러 호출이 동일한 결과를 반환하지 않을 수 있다는 것입니다. (안정된 결과를 원하면 findFirst()대신 사용하십시오.)

따라서 더 간단하게 말하면 Stream의 첫 번째 요소를 선택하거나 선택하지 않을 수 있습니다.

현재 Oracle 특정 구현에서는 병렬이 아닌 파이프 라인의 첫 번째 요소를 반환 할 것이라고 믿습니다. 그러나 병렬 파이프 라인에서는 항상 그렇지는 않습니다.

System.out.println(IntStream.range(0, 100).parallel().findAny());

OptionalInt[50]내가 그것을 실행했을 때 그것은 돌아왔다 . 어쨌든 그것에 의존 해서는 안됩니다 .


답변

findFirst는 스트림의 첫 번째 요소를 반환하지만 findAny는 스트림의 모든 요소를 ​​자유롭게 선택할 수 있습니다.

List<String> lst1 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
List<String> lst2 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");

Optional<String> findFirst = lst1.parallelStream().filter(s -> s.startsWith("D")).findFirst();
Optional<String> fidnAny = lst2.parallelStream().filter(s -> s.startsWith("J")).findAny();

System.out.println(findFirst.get()); //Always print David
System.out.println(fidnAny.get()); //Print Jack/Jill/Julia :behavior of this operation is explicitly nondeterministic


답변

병렬 모드에서는 findAny순서가 보장되지 않지만 그렇습니다 findFirst.

차이점을 보여주기 위해 코드 스 니펫을 작성 했습니다.


답변

스트림에서 findFirst 및 findAny는 첫 번째 요소를 반환하고 나머지는 실행하지 않지만 parallelStream에서는 순서를 말할 수 없으며 parallelStream은 나머지 컬렉션을 실행합니다.

참고

시간 1:25:00


답변

findFirst()그리고 findAny()사용하는 동안 조심하십시오 .

(그 자바 독부터 같이 여기여기 ) 두 방법 스트림에서 임의의 요소를 리턴 – 스트림은 가지고 있지 않는 상대 순서 케이스되는, findFirst()하면서 첫 번째 요소를 반환 findAny()모든 요소를 반환한다.

listISBN과 BOOK 이름으로 구성된 사용자 정의가 있다고 가정합니다 . 시나리오는 다음 예를 참조하십시오.

public class Solution {
   private Integer ISBN;
   private String BookName;

public Solution(int i, String string) {
    ISBN =i;
    BookName = string;
}
//getters and setters
}

public static void main(String[] args) {
        List<Solution> Library = Arrays.asList(new Solution(12,"Java in Action"),new Solution(13,"Java 8"),new Solution(15,"Java 8 Features"),new Solution(16,"Java in Action"));
 System.out.println(Library.stream()
        .map(p->p.getBookName())
        .sorted(Comparator.reverseOrder())
        .findFirst());
    }

출력 :Optional[Java in Action]

책 이름은 같지만 ISBN 번호가 다른 경우가있을 수 있습니다.이 경우 책을 정렬하고 찾는 것이 매우 유사 할 수 있으며 findAny()잘못된 결과를 제공합니다. 5 권의 책이 “Java Reference”로 명명되었지만 ISBN 번호가 다르고 findFirst()이름별로 책이 findAny().

다음과 같은 시나리오를 생각해보십시오.

 ISBN    Name Of book
+-----+------------------+
| 100 | Java-8 in Action |
+-----+------------------+
| 101 | Java-8 in Action |
+-----+------------------+
| 102 | Java-8 in Action |
+-----+------------------+
| 103 | Java-8 in Action |
+-----+------------------+
| 104 | Java-8 in Action |
+-----+------------------+

여기서 findFirst () 및 findAny ()는 BookByName 으로 정렬하더라도 동일한 결과를 제공 합니다.

자세한 기사 :


답변

주문 Stream이없는 시기 findFirst()findAny()동일합니다. 그러나 Stream주문 findAny()하면 더 좋을 것입니다.