Пересечение двух списков объектов в Java 8 - PullRequest
0 голосов
/ 16 декабря 2018

Пересечение двух списков объектов в Java 8. Может ли кто-нибудь сказать мне, что я делаю не так?

List<Student> originalStudent = new ArrayList<>();
List<Student> newStudent = new ArrayList<>();

List<Student> intersectListStudent = new LinkedList<>()

originalStudent.add(new Student("William", "Tyndale",1));
originalStudent.add(new Student("Jonathan", "Edwards",2));
originalStudent.add(new Student("Martin", "Luther"),3);

newStudent.add(new Student("Jonathan", "Edwards",2));
newStudent.add(new Student("James", "Tyndale",4));
newStudent.add(new Student("Roger", "Moore",5));


originalStudent.forEach(n ->
        newStudent.stream()
                .filter(db -> !n.getName().equals(db.getName()) &&
                        !n.getLastName().equals(db.getLastName()))
                    .forEach(student-> intersectListStudent .add(student)));

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Что вы можете сделать, это построить SortedSet<Student> из двух составных списков originalStudent и newStudent.Сортированный набор использует Comparator.comparing(Student::getName).thenComparing(Student::getLastName) в качестве компаратора.

Stream.concat(originalStudent.stream(), newStudent.stream())
    .collect(Collectors.toCollection(() -> new TreeSet<>(
        Comparator.comparing(Student::getFname)
            .thenComparing(Student::getLname))
    ))
0 голосов
/ 16 декабря 2018

Кто-нибудь может сказать мне, что я делаю не так?

Вы нарушаете Побочные эффекты принцип , который в двух словах говорит, что поток не должен изменять другую коллекцию при выполнении действий через конвейеры.Я не проверял ваш код, однако вам не следует обрабатывать потоки.


Как это сделать лучше?

Просто используйтеList::contains в предикате фильтра, чтобы избавиться от уникальных значений.

List<Student> students = originalStudent.stream()
                                        .filter(newStudent::contains)
                                        .collect(Collectors.toList());

Это решение (понять метод List::contains) основано нареализовано сравнение на равенство с использованием Object::equals.Следовательно, необходимо переопределить тот же метод в классе Student.

Редактировать: Пожалуйста, имейте в виду, что автоматическое переопределение Object::equals помнит id для вычисления равенства.Поэтому равенство будет основываться только на имени и фамилии.(спасибо @ nullpointer ).

Без переопределения Object::equals?

Вы должны выполнить сравнение в filter, используядругой stream и метод Stream::anyMatch, который возвращает true, если предикат квалифицирован.

List<Student> students = originalStudent.stream()
              .filter(os -> newStudent.stream()                    // filter
                  .anyMatch(ns ->                                  // compare both
                       os.getName().equals(ns.getName() &&         // name
                       os.getLastName().equals(ns.getLastName()))) // last name
              .collect(Collectors.toList());
...