1.概要
Java 8 Stream API中有两个经常被混淆和误用的方法: FindAny() 和 findFirst() 。
本教程中,我们将对比这两种方法的差异,以及何时使用它们。
2.使用 stream.FindAny()
顾名思义, FindAny() 返回 stream 中任意一个元素:
如果 Stream 为空,则该方法返回为空的 Optional 实例:
@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")));
}
在串行流中,大多数情况下会返回第一个元素,但并不绝对保证。
在并行流下,为了获得最佳性能,此时得到的结果不可预测,findAny 通常会返回最快处理完的那个线程的数据:
@Test
public void createParallelStream_whenFindAnyResultIsPresent_thenCorrect()() {
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.使用 stream.findFirst()
findfirst() 每次都会返回stream中的第一个元素。
当遇到非 encounter order 流时,它会返回stream中的任何元素。 java.util.streams 文档中提到:
某些流的返回的元素是有确定顺序的,我们称之为 encounter order。这个顺序是流提供它的元素的顺序,比如数组的encounter order是它的元素的排序顺序,List是它的迭代顺序(iteration order),对于HashSet,它本身就没有encounter order。 一个流是否是encounter order主要依赖数据源和它的中间操作。
返回类型也是一个 Optional 实例:
@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"));
}
4.总结
在本教程中,我们研究了Java 8 stream API的 findAny() 和 findFirst() 方法。 findAny() 方法返回流中任何元素,而 findFirst() 方法返回流中的第一个元素。
本文完整源代码存放在GitHub。