如何从 Java 8 Streams 中的 forEach 循环获取列表输出

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50618049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:43:08  来源:igfitidea点击:

How to get a list output from forEach loop in Java 8 Streams

javajava-8java-stream

提问by Ravi

I have two different lists of same objects but different properties and with a common identifier in those objects. I would like to iterate over the first list and get the corresponding object from the second (which has common properties) and then wrap those objects around and finally add that object to a list using Java Streams.

我有两个不同的相同对象列表,但具有不同的属性,并且在这些对象中有一个共同的标识符。我想遍历第一个列表并从第二个列表(具有公共属性)获取相应的对象,然后将这些对象包装起来,最后使用 Java Streams 将该对象添加到列表中。

This is the example I have taken.

这是我所举的例子。

private class Person {
        private String name;
        private boolean isSenior;

        private Person(String name, boolean isSenior) {
            this.name = name;
            this.isSenior = isSenior;
        }

        public String getName() {
            return name;
        }

        public boolean isSenior() {
            return isSenior;
        }

        @Override
        public String toString() {
            return name + ": " + isSenior;
        }
    }

    private class PersonWrapper {
        private Person jrPerson;
        private Person srPerson;

        private PersonWrapper(Person jrPerson, Person srPerson) {
            this.jrPerson = jrPerson;
            this.srPerson = srPerson;
        }

        public Person getJrPerson() {
            return jrPerson;
        }

        public Person getSrPerson() {
            return srPerson;
        }

        @Override
        public String toString() {
            return jrPerson.toString() + "-" + srPerson.toString();
        }
    }

Now, in the main class, I will create two list instances like this

现在,在主类中,我将创建两个这样的列表实例

List<Person> jrPersons = new ArrayList<>();
List<Person> srPersons = new ArrayList<>();

and add the objects in the following manner

并按以下方式添加对象

jrList.add(new Person("John", false));
jrList.add(new Person("Paul", false));
jrList.add(new Person("Mike", false));

seniorList.add(new Person("John", true));
seniorList.add(new Person("Paul", true));
seniorList.add(new Person("Mike", true));

Now, I want to iterate over the jrList and find the corresponding Person object in the srList (same name). Then I would wrap these objects as PersonWrapperand that object to a list.

现在,我想遍历 jrList 并在 srList(同名)中找到相应的 Person 对象。然后我会将这些对象包装PersonWrapper成一个列表。

So far, this is what I have been doing

到目前为止,这就是我一直在做的

List<PersonWrapper> wrapperList = new ArrayList<>();

jrList.forEach(jr -> seniorList.stream().filter(sr -> jr.getName().equals(sr.getName())).map(sr -> new PersonWrapper(jr, sr)).collect(Collectors.toList()));

Now, I would like to know how the Collectors.toList()can be substituted by wrapperListor how the output from Collectors.toList()be added to wrapperList.

现在,我想知道如何Collectors.toList()替换wrapperList或如何将输出Collectors.toList()添加到wrapperList.

Please help me in achieving this.

请帮助我实现这一目标。

采纳答案by Ousmane D.

While Lino'sanswer is certainly correct. I would argue that if a given person object in jrListcan only ever have one corresponding match in seniorListmaximum, in other words, if it's a 1-1 relationship then you can improve upon the solution given by Linoby finding the first match as follows:

Lino 的回答当然是正确的。我会争辩说,如果给定的人对象jrList最多只能有一个对应的匹配项,seniorList换句话说,如果它是 1-1 关系,那么您可以通过查找第一个匹配项来改进Lino给出的解决方案,如下所示:

List<PersonWrapper> resultSet = jrList.stream()
                .map(p -> seniorList.stream()
                        .filter(sr -> p.getName().equals(sr.getName()))
                        .findFirst()
                        .map(q -> new PersonWrapper(p, q))
                        .get())
                .collect(Collectors.toList());

or if there is no guarantee that each person in jrListwill have a corresponding match in seniorListthen change the above query to:

或者如果不能保证每个人jrList都会有相应的匹配项,seniorList那么将上面的查询更改为:

List<PersonWrapper> resultSet = jrList.stream()
                .map(p -> seniorList.stream()
                        .filter(sr -> p.getName().equals(sr.getName()))
                        .findFirst()
                        .map(q -> new PersonWrapper(p, q))
                        .orElse(null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

The difference is that now instead of calling get()on the result of findFirst()we provide a default with orElsein case findFirstcannot find the corresponding value and then we filterthe nullvalues out in the subsequent intermediate operation as they are not needed.

不同之处在于,现在不是调用get()结果,findFirst()而是我们提供默认值,orElse以防万一findFirst找不到相应的值,然后我们在后续的中间操作中将不需要filternull值输出。

回答by Lino

Instead of using a forEachjust use streams from the beginning:

而不是forEach从一开始就使用 just use 流:

List<PersonWrapper> wrapperList = jrList.stream()
    .flatMap(jr -> seniorList.stream()
         .filter(sr -> jr.getName().equals(sr.getName()))
         .map(sr -> new PersonWrapper(jr, sr))
    )
    .collect(Collectors.toList());

By using flatMapyou can flattena stream of streams (Stream<Stream<PersonWrapper>>) into a single stream (Stream<PersonWrapper>)

通过使用,flatMap您可以将流 ( )流平展Stream<Stream<PersonWrapper>>为单个流 ( Stream<PersonWrapper>)

If you can't instantiate wrapperListby yourself or really need to append to it. You can alter above snippet to following:

如果你不能自己实例化wrapperList或者真的需要附加到它。您可以将上述代码段更改为以下内容:

List<PersonWrapper> wrapperList = new ArrayList<>();

jrList.stream()
    .flatMap(jr -> seniorList.stream()
         .filter(sr -> jr.getName().equals(sr.getName()))
         .map(sr -> new PersonWrapper(jr, sr))
    )
    .forEach(wrapperList::add);

回答by Dharita Chokshi

Replace your looping logic with below code.

用下面的代码替换你的循环逻辑。

 jrList.forEach(jr -> seniorList.stream().filter(sr -> jr.getName().equals(sr.getName()))
                    .map(sr -> wrapperList.add(new PersonWrapper(jr, sr))).collect(Collectors.toList()));