我有点困惑于Java 8中Stream
API的Stream#findAny()
和Stream#findFirst()
之间的区别。
我的理解是,它们都将返回与过滤器匹配的第一个元素。那么为什么要有两种方法来完成相同的任务呢?我是否遗漏了什么?
我有点困惑于Java 8中Stream
API的Stream#findAny()
和Stream#findFirst()
之间的区别。
我的理解是,它们都将返回与过滤器匹配的第一个元素。那么为什么要有两种方法来完成相同的任务呢?我是否遗漏了什么?
Stream#findAny()
:当使用Stream.findFirst()
时,它将返回一个Optional<T>
,描述了流的严格第一个元素。 Stream
类没有.findOne()
方法,所以我想你的意思是.findFirst()
。
Stream.findAny()
(重点在于“some element”):findFirst()
。)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
[1]我已经开发了一小段代码来测试流的findAny和findFirst。我创建了1000万个虚拟数据,并使用并行流和顺序流过滤这些数据,然后应用findAny和findFirst。
从这个小实验中,我发现findAny和findFirst给出相同的结果,并且在顺序流中提供第一个结果。但是我发现,在parallelStream中,findAny不能保证每次产生相同的结果,而findFirst则保证它无论流是并行还是顺序,始终产生相同的结果。
public class TestFilter {
static class Employee {
String name;
double salary;
long id;
public Employee(String name, long id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
String genNextName() {
return "Emp-" + (this.id + 1);
}
double genNextSalary() {
return new Random().nextDouble() * 1000000;
}
long genNextId() {
return this.id + 1;
}
@Override
public String toString() {
return this.id + " " + this.name + " " + this.salary + "\n";
}
}
public static void main(String[] args) {
List<Employee> employees = createDummyEmployee(10000000l);
List<Employee> emps = null;
long time = 0;
for (int i = 0; i < 50; i++) {
Optional<Employee> e1 = employees.stream()
.filter(e -> e.name.endsWith("999"))
.filter(e -> e.salary > 10000)
.filter(e -> e.id % 2 == 1)
.findAny();
Optional<Employee> e2 = employees.stream()
.filter(e -> e.name.endsWith("999"))
.filter(e -> e.salary > 10000)
.filter(e -> e.id % 2 == 1)
.findFirst();
Optional<Employee> pe1 = employees.parallelStream()
.filter(e -> e.name.endsWith("999"))
.filter(e -> e.salary > 10000).filter(e -> e.id % 2 == 1)
.findAny();
Optional<Employee> pe2 = employees.parallelStream()
.filter(e -> e.name.endsWith("999"))
.filter(e -> e.salary > 10000)
.filter(e -> e.id % 2 == 1)
.findFirst();
System.out.print("FindAny without parallel : " + (e1.isPresent() ? e1.get().id +"": "null"));
System.out.print(" | FindFirst without parallel : " + (e2.isPresent() ? e2.get().id +"": "null"));
System.out.print(" | FindAny by Parallel : " + (pe1.isPresent() ? pe1.get().id +"": "null"));
System.out.print(" | FindFirst by Parallel : " + (pe2.isPresent() ? pe2.get().id +"": "null"));
System.out.println();
}
}
public static List<Employee> createDummyEmployee(long n) {
Employee e1 = new Employee("Emp-1", 1l, 1.0);
return Stream.iterate(e1, (Employee e) -> new Employee(e.genNextName(), e.genNextId(), e.genNextSalary()))
.limit(n).collect(Collectors.toList());
}
}
[实验结果] [1]: https://istack.dev59.com/HOZjA.webp
findFirst()
和 findAny()
。findFirst()
返回第一个元素,而 findAny()
则返回任意一个元素。list
,包含 ISBN 和书名。对于一个场景,请看以下示例: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());
}
输出: 可选[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()将给出相同的结果。
当Stream
无序时,findFirst()
和findAny()
是相同的。但是当Stream
有序时,findAny()
会更好。
Stream
是什么意思?它总是有序的(当它没有并行化时,在给定的Stream
上执行操作的顺序每次都相同),但可能不是由用户排序的。 - Jezor
filter
,findAny
仍然可以返回任何元素,包括不符合所应用的过滤器的元素? - Koray TugayfindAny
可以从中返回任何一个元素(在并行流操作中可能是随机的)。 - KrishPrabakar