当前位置:  开发笔记 > 编程语言 > 正文

java8 Stream的filter()和map()方法是否使用迭代?

如何解决《java8Stream的filter()和map()方法是否使用迭代?》经验,为你挑选了1个好方法。

我有一个POJOPerson.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;    
    }
}

然后我有一个Demo.java文件,它创建一个人员列表,并使用流来过滤和打印列表中的内容:

import java.util.*;

public class Demo {
    public static void main(String[] args) {
        List people = createPeople();
        List names = people.stream()
                                   .filter(person -> person.isAdult())
                                   .map(person -> person.getName())
                                   .collect(toList());
        System.out.println(names);
    }

    private static List createPeople() {
        List 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;
    }
}  

我想知道:

1>是否filter()map()内部使用循环迭代所有Person对象List people

2>如果是,它们是否会在列表中的两个不同时间循环遍历所有对象(第一次迭代filter()和另一次map())?

3>如果是,再次,如果我添加另一个map()filter()方法,它会第三次循环遍历所有对象吗?

4>如果是,那么它与传统的命令式样式编码有什么不同的性能(实际上,在传统的命令式样式中,我们可以在大多数时间内在单个循环中完成所有的过滤和映射.所以性能明智,在这种情况下,命令式样式编码比流更好.)?

PS:如果有No上述任何一个问题,请添加有关事情如何运作的解释.

还有一点:内部流完成的迭代和我们以命令式风格进行的迭代是否存在差异?请详细解释一下我的知识.



1> Andreas..:

首先,你的代码不能编译,因为map()返回a Stream而不是a List.你必须结束流链与终端操作,并且两者filter()map()是中间操作.在javadoc说得那么正确.在您的情况下,您需要添加.collect(Collectors.toList())以使其编译并运行正常.

1>是否filter()map()内部使用一个循环来遍历所有Person的对象List的人吗?

不.终端操作正在进行循环.

由于问题2到4假定Yes答案,他们没有答案.

如果有No上述任何问题,请添加有关事情如何运作的说明.

阅读文档,或搜索网络.这很好解释.

流内部的迭代和我们在命令式样式中进行的迭代是否存在差异?

是的,例如,流可以利用并行线程执行.即使是单线程,整个操作的工作方式也有所不同,尽管从逻辑上讲,它们在高级别上基本相同.


在您的代码中,collect()添加了调用,等效的命令式代码将是:

List names = new ArrayList<>();
for (Person person : people)
    if (person.isAdult())
        names.add(person.getName());

要比较流逻辑的作用,首先要定义传递给的lambda filter()map():

Predicate        filter = person -> person.isAdult();
Function map    = person -> person.getName();

然后你Collector通过调用得到Collectors.toList()它,并检索它提供的对象:

Collector, List> collector = (Collector) Collectors.toList();
Supplier>               supplier    = collector.supplier();
BiConsumer, String>     accumulator = collector.accumulator();
Function, List> finisher    = collector.finisher();

现在,stream()调用基本上提供了一个Iterator(它实际上是一个Spliterator)并且collect调用将迭代,因此组合它们等同于for循环.我不会讨论如何充分逻辑Stream,Spliteratorcollect()作品.如果您需要更多详细信息,请在网上搜索.

因此,for上面的命令循环变为:

List 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 names = finisher.apply(list); // names = list

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有