Как получить вывод списка из цикла forEach в Java 8 Streams - PullRequest
0 голосов
/ 31 мая 2018

У меня есть два разных списка одних и тех же объектов, но разных свойств и с общим идентификатором в этих объектах.Я хотел бы перебрать первый список и получить соответствующий объект из второго (который имеет общие свойства), а затем обернуть эти объекты вокруг и, наконец, добавить этот объект в список с помощью потоков Java.

ЭтоПример, который я взял.

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();
        }
    }

Теперь в основном классе я создам два экземпляра списка, как этот

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

, и добавлю объекты следующим образом

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));

Теперь я хочу перебрать jrList и найти соответствующий объект Person в srList (то же имя).Затем я бы обернул эти объекты как 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()));

Теперь я хотел бы знать, какCollectors.toList() можно заменить на wrapperList или как добавить к wrapperList вывод из Collectors.toList().

Пожалуйста, помогите мне в достижении этого.

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

Замените вашу логику с кодом ниже.

 jrList.forEach(jr -> seniorList.stream().filter(sr -> jr.getName().equals(sr.getName()))
                    .map(sr -> wrapperList.add(new PersonWrapper(jr, sr))).collect(Collectors.toList()));
0 голосов
/ 31 мая 2018

Пока Ответ Лино , безусловно, правильный.Я бы сказал, что если у данного объекта персонажа в 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());

или если нет гарантии, что у каждого человека в 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());

Разница в том, что теперь вместо вызова get() для результата findFirst() мы предоставляем значение по умолчанию orElse в случае, если findFirst не может найти соответствующее значение, а затем мы filternull значения в последующей промежуточной операции, поскольку они не нужны.

0 голосов
/ 31 мая 2018

Вместо использования 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());

Используя 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);
...