Java 8中findAny()和findFirst()之间的区别


90

我对Java 8中的 APIStream#findAny()和一点都不感到困惑。Stream#findFirst()Stream

我了解到的是,例如当与filter一起使用时,两者都会从流中返回第一个匹配的元素?

那么,为什么要用两种方法完成同一任务?我想念什么吗?

Answers:


92

我了解到的是,例如当与filter一起使用时,两者都会从流中返回第一个匹配的元素?

这不是真的。根据javadoc Stream#findAny()

返回Optional<T>描述流中某些元素的描述; Optional<T>如果流为空,则返回空。该操作的行为明确地是不确定的。可以自由选择流中的任何元素。这是为了在并行操作中获得最佳性能。

whileStream.findFirst()严格返回Optional<T>描述流的第一个元素。该班没有一个方法,所以我想你的意思。Stream.findOne().findFirst()


我还是不明白,所以您说的是即使filter应用a之后,findAny也可以返回任何元素,包括与应用的过滤器不匹配的元素吗?
Koray Tugay

@KorayTugay-不,过滤器之后,无论存在任何剩余元素,findAny都可以(随机)返回该元素中的任何元素,尤其是在并行流操作中
KrishPrabakar

46

不,两者都不会返回Stream的第一个元素。

来自Stream.findAny()(强调我的):

返回Optional描述流中某些元素的描述;Optional如果流为空,则返回空。

这是短路端子操作。

该操作的行为明确地是不确定的。可以自由选择流中的任何元素。这是为了在并行操作中获得最佳性能。代价是对同一源的多次调用可能不会返回相同的结果。(如果需要稳定的结果,请findFirst()改用。)

因此,简单地说,它可能会或可能不会选择Stream的第一个元素。

对于当前特定于Oracle的实现,我相信它将返回非并行管道中的第一个元素。但是,在并行管道中,它并不总是(例如执行System.out.println(IntStream.range(0, 100).parallel().findAny());OptionalInt[50]当我运行它时返回)。无论如何,您一定不能依靠它。


16

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

1

在并行模式下,findAny不能保证顺序,但是findFirst可以。

我写了一些代码片段来显示差异,请访问它


1

在流findFirst和findAny中返回第一个元素,不执行其余元素,但在parallelStream中,说顺序是不可行的,而parallelStream执行集合的其余部分。

参考

时间1:25:00


1

我只想说,当谨慎findFirst()findAny()同时使用。

从它们的Javadoc(此处此处)开始,这两个方法都从流中返回一个任意元素-除非流具有遇到顺序,在这种情况下,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参考”,但是具有不同的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 |
+-----+------------------+

即使按BookByName排序,这里的findFirst()和findAny()也会给出相同的结果

详细文章:


-1

什么时候Stream是无序的,findFirst()并且findAny()是相同的。但是Stream订购时findAny()会更好。


这是不正确的。这些方法都不是“更好的”,因为它们的行为和用例是完全不同的。另外,Stream“被命令”是什么意思?它始终是有序的(Stream每次未并行化时,操作都将以给定的顺序执行),但可能不是由用户排序的。
耶佐
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.