Java лямбда пересечение двух списков и удаление из результата - PullRequest
0 голосов
/ 30 августа 2018

Я хочу использовать лямбда-выражение Java для пересечения двух списков, а затем всегда с лямбда-выражением, которое хочу удалить из списка.

Пример: у меня есть

List<Person> first = new ArrayList<Person>(); 
List<Person> second = new ArrayList<Person>(); 

Предположим, что в обоих списках есть какой-то объект Person. Я хочу положить в список временного пересечения двух списков, отфильтрованных по имени, например:

List<Person> temp = new ArrayList<>();
for (Person one : first) {
     for (Person two : second) {                        
        if(one.getName.equals(two.getName)) {
                        temp.add(two);
         }
     }
}

Затем я хочу удалить человека из Temp, используя фильтр, например, используя Фамилию.

for (Person tmp : temp) {
     for (Person one : first) {
        if (one.getSurname.equals(tmp.getSurname)) {
              temp.remove(tmp);
        }
     }
}

Я хочу использовать лямбда-выражение, Как я могу это сделать?

Ответы [ 5 ]

0 голосов
/ 30 августа 2018

Вот решение по ссылке на метод и not.

second.stream()
     .filter(first.stream.map(Person::getName).collect(toSet())::contains)
     .filter(not(first.stream.map(Person::getSurname).collect(toSet())::contains))
     .collect(toList());

Я не написал код в IDE. могут быть некоторые ошибки компилятора.

0 голосов
/ 30 августа 2018

Оба for-loop s могут быть сжаты в два Stream::filter метода:

List<Person> temp = second.stream()
    .filter(s ->  first.stream().anyMatch(f -> f.getName().equals(s.getName())))
    .filter(s -> !first.stream().anyMatch(f -> f.getSurame().equals(s.getSurame())))
    .collect(Collectors.toList());
0 голосов
/ 30 августа 2018

Лямбды не всегда являются лучшим решением.

Вы можете использовать метод retainAll из Collection<E>.

fist.retainAll(second);
0 голосов
/ 30 августа 2018

Пересечение между first и second:

List<Person> intersection = first.stream()
        .filter(p1 -> second.stream().anyMatch(p2 -> p2.getName().equals(p1.getName())))
        .collect(Collectors.toList());

Удалить элементы из myList на основе элементов из first:

first.stream()
    .filter(p1 -> myList.stream().anyMatch(p2 -> p1.getSurName().equals(p2.getSurName())))
    .forEach(myList::remove);
0 голосов
/ 30 августа 2018

Вы можете сделать это так,

Map<String, Set<String>> nameToSurname = second.stream().collect(
        Collectors.groupingBy(Person::getName, 
            Collectors.mapping(Person::getSurname, Collectors.toSet())));
List<Person> temp = first.stream().filter(p -> nameToSurname.get(p.getName()) != null)
                .filter(p -> !nameToSurname.get(p.getName()).contains(p.getSurname()))
                .collect(Collectors.toList());

Сначала создайте map от mame до всех surnames с этим именем, используя второй список. Затем выполните итерацию по первому списку, для каждого человека, проверьте, есть ли значение на карте, передавая имя в качестве ключа. Если это так, то проверьте, соответствуют ли фамилии текущего человека. Если оба критерия удовлетворены, соберите его в контейнер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...