обрабатывать дубликат ключа в функции Collectors.toMap () - PullRequest
0 голосов
/ 10 января 2019

Я создаю карту, которая (ключ, значение) будет (имя, адрес) в моем объекте Person:

Map<String, String> myMap = persons.stream.collect(Collector.toMap(person.getName(), person.getAddress(), (address1, address2) -> address1));

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

(address1, address2) -> {
                           System.out.println("duplicate "+person.name() + " is found!");
                           return address1;
                        }

Я застреваю, передавая объект person этой функции слияния.

Ответы [ 4 ]

0 голосов
/ 13 января 2019

Вот еще одна возможность, используя peek

import java.util.*;
import java.util.stream.*;

class App {
    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(new Person("foo", "bar"), new Person("baz", "qux"), new Person("foo", "zuz"));

        Set<String> names = new HashSet<>();
        Map<String, String> nameAddress = persons.stream().peek(p -> {
            if (names.contains(p.getName())) {
                System.out.println("Duplicate key being skipped: " + p);
            } else {
                names.add(p.getName());
            }
        }).collect(Collectors.toMap(person -> person.getName(), person -> person.getAddress(), (addr1, addr2) -> addr1));

    }
}

class Person {
    String name;
    String address;

    public Person(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }

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

Вывод для меня будет следующим для фрагмента выше:

Duplicate key being skipped: foo zuz
0 голосов
/ 10 января 2019

@ Aomine: решение выглядит хорошо и работает для меня тоже. Просто хотел подтвердить, что с этим он повторяется дважды правильно ?? Потому что с помощью простого решения, как показано ниже, оно повторяется только один раз, но достигается то, что требуется.

Map<String,String> myMap= new HashMap<>();
persons.stream().foreach(item-> {
    if(myMap.containsKey(item.getName()))
        {/*do something*/}
    else 
        myMap.put(item.getName(),item.getAddress());
});
0 голосов
/ 10 января 2019

Я считаю, что подход forEach вместе с Map.merge был бы намного проще и соответствовал бы текущему варианту использования:

Map<String, String> myMap = new HashMap<>();
persons.forEach(person -> myMap.merge(person.getName(), person.getAddress(), (adrs1, adrs2) -> {
    System.out.println("duplicate " + person.getName() + " is found!");
    return adrs1;
}));

Примечание : Map.merge также использует BiFunction (родительский элемент BinaryOperator, используемый в toMap), поэтому вы можете легко соотнести здесь функцию слияния с существующими желаемыми функциями.

0 голосов
/ 10 января 2019

если вы хотите получить доступ ко всему объекту person в функции слияния, тогда передайте Function.identity() для valueMapper:

Map<String, Person> myMap = 
        persons.stream()
               .collect(toMap(p -> p.getName(), 
                      Function.identity(), // or p -> p
                     (p1, p2) -> { /* do logic */ }));

Но, как вы можете видеть, получающиеся значения карты являются Person объектами, если вы все еще хотите получить Map<String, String> в качестве результата и по-прежнему обращаться ко всему объекту Person в mergeFunction, тогда вы можете сделать следующее:

 persons.stream()
         .collect(toMap(p -> p.getName(), Function.identity(),(p1, p2) -> { /* do logic */ }))
         .entrySet()
         .stream()
         .collect(toMap(Map.Entry::getKey, p -> p.getValue().getAddress()));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...