it-swarm.com.ru

Разница между findAny () и findFirst () в Java 8

Я немного запутался между Stream#findAny() и Stream#findFirst() API Stream в Java 8.

Я понял, что оба возвращают первый соответствующий элемент из потока, например, при использовании вместе с фильтром?

Итак, почему два метода для одной и той же задачи? Я что-то пропустил?

51
Mandeep Rajpal

Я понял, что оба возвращают первый соответствующий элемент из потока, например, когда используется вместе с фильтром?

Это не правда. Согласно Javadoc, Stream#findAny() :

Возвращает Optional<T>, описывающий some элемент потока, или пустой Optional<T>, если поток пустой . Поведение этой операции явно недетерминировано; свободно выбирать любой элемент в потоке. Это позволяет обеспечить максимальную производительность при параллельных операциях;

while Stream.findFirst() вернет Optional<T>, описывающий строго первый элемент потока. Класс Stream не имеет метода .findOne(), поэтому я предполагаю, что вы имели в виду .findFirst().

59
Konstantin Yovkov

Нет, оба не вернут первый элемент потока.

От Stream.findAny() (выделено мое):

Возвращает Optional, описывающую некоторый элемент потока, или пустую Optional, если поток пуст.

Это операция короткого замыкания терминала.

Поведение этой операции явно недетерминировано; можно свободно выбирать любой элемент в потоке. Это позволяет обеспечить максимальную производительность при параллельных операциях; цена заключается в том, что несколько вызовов одного и того же источника могут не возвращать один и тот же результат. (Если требуется стабильный результат, используйте вместо него findFirst().)

Проще говоря, он может или не может выбрать первый элемент потока. 

Я полагаю, что в текущей конкретной реализации Oracle он вернет первый элемент в непараллельном конвейере. Тем не менее, в параллельном конвейере, это не всегда (выполнить, например, System.out.println(IntStream.range(0, 100).parallel().findAny());, он вернул OptionalInt[50], когда я его запустил). В любом случае, вы должны не полагаться на это.

33
Tunaki

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
3
Amir

в параллельном режиме findAny не гарантирует порядок, но findFirst делает.

Я написал фрагмент кода, чтобы показать разницу, посетите его

1
jiahut

В потоке findFirst и findAny возвращают первый элемент и не выполняют остальное, но в parallelStream нельзя сказать, что порядок, а parallelStream выполняет остальную часть коллекции.

Ссылка

Время 1:25:00

0
emon

Я просто скажу, что остерегайтесь findFirst() и findAny() при использовании.

Начиная с их Javadoc ( здесь и здесь ) оба метода возвращают произвольный элемент из потока - если только поток не имеет порядок встречи, в этом случае findFirst() возвращает первый элемент в то время как findAny() вернет любой элемент.

Предположим, у нас есть пользовательская переменная list, состоящая из имени ISBN и 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());
    }

Output: Optional[Java in Action]

Могут быть сценарии, когда имя книги совпадает, но номера ISBN разные, в этом случае сортировка и поиск книги могут быть очень похожи на findAny() и приведут к неверному результату. Подумайте о сценарии, в котором 5 книг названы «Справочник по Java», но имеют разные номера 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.

Подробная статья: 

0
Common Man