Adi*_*ngh 6 java iteration java-8 java-stream
我有一个POJO在Person.java文件中:
public class Person {
private String name;
private int age;
public Person(String n, int a) {
name = n;
age = a;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isAdult() {
return getAge() >= 18;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个Demo.java文件,它创建一个人员列表,并使用流来过滤和打印列表中的内容:
import java.util.*;
public class Demo {
public static void main(String[] args) {
List<Person> people = createPeople();
List<String> names = people.stream()
.filter(person -> person.isAdult())
.map(person -> person.getName())
.collect(toList());
System.out.println(names);
}
private static List<Person> createPeople() {
List<Person> people = new ArrayList<>();
people.add("John", 19);
people.add("Joe", 21);
people.add("Jill", 16);
people.add("Sylvester", 18);
people.add("Hillary", 17);
people.add("Donald", 4);
return people;
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道:
1>是否filter()和map()内部使用循环迭代所有Person对象List people?
2>如果是,它们是否会在列表中的两个不同时间循环遍历所有对象(第一次迭代filter()和另一次map())?
3>如果是,再次,如果我添加另一个map()或filter()方法,它会第三次循环遍历所有对象吗?
4>如果是,那么它与传统的命令式样式编码有什么不同的性能(实际上,在传统的命令式样式中,我们可以在大多数时间内在单个循环中完成所有的过滤和映射.所以性能明智,在这种情况下,命令式样式编码比流更好.)?
PS:如果有No上述任何一个问题,请添加有关事情如何运作的解释.
还有一点:内部流完成的迭代和我们以命令式风格进行的迭代是否存在差异?请详细解释一下我的知识.
And*_*eas 10
首先,你的代码不能编译,因为map()返回a Stream而不是a List.你必须结束流链与终端操作,并且两者filter()和map()是中间操作.在javadoc说得那么正确.在您的情况下,您需要添加.collect(Collectors.toList())以使其编译并运行正常.
1>是否
filter()和map()内部使用一个循环来遍历所有Person的对象List的人吗?
不.终端操作正在进行循环.
由于问题2到4假定Yes答案,他们没有答案.
如果有
No上述任何问题,请添加有关事情如何运作的说明.
阅读文档,或搜索网络.这很好解释.
流内部的迭代和我们在命令式样式中进行的迭代是否存在差异?
是的,例如,流可以利用并行线程执行.即使是单线程,整个操作的工作方式也有所不同,尽管从逻辑上讲,它们在高级别上基本相同.
例
在您的代码中,collect()添加了调用,等效的命令式代码将是:
List<String> names = new ArrayList<>();
for (Person person : people)
if (person.isAdult())
names.add(person.getName());
Run Code Online (Sandbox Code Playgroud)
要比较流逻辑的作用,首先要定义传递给的lambda filter()和map():
Predicate<Person> filter = person -> person.isAdult();
Function<Person, String> map = person -> person.getName();
Run Code Online (Sandbox Code Playgroud)
然后你Collector通过调用得到Collectors.toList()它,并检索它提供的对象:
Collector<String, List<String>, List<String>> collector = (Collector) Collectors.toList();
Supplier<List<String>> supplier = collector.supplier();
BiConsumer<List<String>, String> accumulator = collector.accumulator();
Function<List<String>, List<String>> finisher = collector.finisher();
Run Code Online (Sandbox Code Playgroud)
现在,stream()调用基本上提供了一个Iterator(它实际上是一个Spliterator)并且collect调用将迭代,因此组合它们等同于for循环.我不会讨论如何充分逻辑Stream,Spliterator和collect()作品.如果您需要更多详细信息,请在网上搜索.
因此,for上面的命令循环变为:
List<String> list = supplier.get(); // list = new ArrayList<>()
for (Person person : people) // collect() loop using Spliterator from stream()
if (filter.test(person)) { // if (person.isAdult())
String value = map.apply(person); // value = person.getName()
accumulator.accept(list, value); // list.add(value)
}
List<String> names = finisher.apply(list); // names = list
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2331 次 |
| 最近记录: |