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

Rav*_*avi 7 java java-8 java-stream

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

这是我采取的例子.

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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

List<Person> jrPersons = new ArrayList<>();
List<Person> srPersons = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

并按以下方式添加对象

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));
Run Code Online (Sandbox Code Playgroud)

现在,我想迭代jrList并在srList(同名)中找到相应的Person对象.然后我将这些对象包装PersonWrapper为一个列表.

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

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()));
Run Code Online (Sandbox Code Playgroud)

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

请帮助我实现这一目标.

Lin*_*ica 12

而不是forEach从一开始就使用刚刚使用的流:

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());
Run Code Online (Sandbox Code Playgroud)

通过使用flatMap你可以扁平化流(流Stream<Stream<PersonWrapper>>)集成到一个流(Stream<PersonWrapper>)

如果你不能自己实例化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);
Run Code Online (Sandbox Code Playgroud)


Ous*_* D. 4

而利诺的回答当然是正确的。我认为,如果给定的 person 对象最多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());
Run Code Online (Sandbox Code Playgroud)

或者,如果不能保证 中的每个人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());
Run Code Online (Sandbox Code Playgroud)

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

  • 从 Java9 开始,您可能希望省略 `orElse()` 并仅使用 `.flatMap(p -&gt; SeniorList.stream() .filter(sr -&gt; p.getName().equals(sr.getName())) .findFirst() .map(q -&gt; new PersonWrapper(p, q)).stream()` 将可选值扁平化为流 (2认同)