Создайте карту из двух разных списков на основе общих условий, используя Java 8 Streams - PullRequest
0 голосов
/ 22 мая 2018

У меня есть два списка таких экземпляров:

List<NameAndAge> nameAndAgeList = new ArrayList<>();
nameAndAgeList.add(new NameAndAge("John", "28"));
nameAndAgeList.add(new NameAndAge("Paul", "30"));
nameAndAgeList.add(new NameAndAge("Adam", "31"));

List<NameAndSalary> nameAndSalaryList = new ArrayList<>();
nameAndSalaryList.add(new NameAndSalary("John", 1000));
nameAndSalaryList.add(new NameAndSalary("Paul", 1100));
nameAndSalaryList.add(new NameAndSalary("Adam", 1200));

, где NameAndAge равно

class NameAndAge {
    public String name;
    public String age;

    public NameAndAge(String name, String age) {
        this.name = name;
        this.age = age;
    }

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

, а NameAndSalary равно

private class NameAndSalary {
    private String name;
    private double salary;

    public NameAndSalary(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

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

Теперь,Я хочу создать карту с ключом как NameAndAge объект из первого списка и значением NameAndSalary из второго списка, где имя совпадает в обоих объектах.

Итак, когда я печатаю карту, это должно выглядеть так:

{John: 28=John: 1000.0}
{Paul: 30=Paul: 1100.0}
{Adam: 31=Adam: 1200.0}

Я пытался сделать это, но конечный тип возврата - 'void', поэтому я застрял в невежестве, поскольку я новичок в Streams.

nameAndAgeList
    .forEach(n ->
        nameAndSalaryList
            .stream()
            .filter(ns -> ns.name.equals(n.name))
            .collect(Collectors.toList()));

Может кто-нибудь сообщить, как этого можно достичь с помощью Java Streams API?

Ответы [ 4 ]

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

Без создания какого-либо промежуточного объекта, без использования forEach, один вкладыш:

Map<NameAndAge, NameAndSalary> resultMap1 = nameAndAgeList.stream()
            .map(nameAndAge -> nameAndSalaryList.stream()
                    .filter(nameAndSalary -> nameAndAge.getName().equals(nameAndSalary.getName()))
                    .map(nameAndSalary -> new SimpleEntry<>(nameAndAge, nameAndSalary))
                    .collect(Collectors.toList()).get(0))
            .collect(Collectors.toMap(simpleEntry -> simpleEntry.getKey(), simpleEntry -> simpleEntry.getValue()));

Вы должны будете добавить функции getter к классам домена.Прямой доступ к свойствам может быть плохой идеей.

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

Это тоже поможет:

Map<NameAndAge, NameAndSalary> map = new HashMap<>();
nameAndAgeList.forEach(age -> {
     NameAndSalary salary = nameAndSalaryList.stream().filter(
              s -> age.getName().equals(s.getName())).
              findFirst().
              orElseThrow(IllegalStateException::new);
      map.put(age, salary);
});

Имейте в виду, что выкинет IllegalStateException, если не найдется подходящее имя.

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

Это тоже должно работать

List<String> commonNames = nameAndAgeList
    .stream()
    .filter(na -> 
         nameAndSalaryList.anyMatch((ns) -> ns.getName().equals(na.getName()))
    .collect(Collectors.toList());

Map<NameAndAge, NameAndSalary> map = 
    commonNames.stream().collect(Collectors.toMap(name -> 
        nameAndAgeList.get(name), name -> nameAndSalaryList.get(name)));
0 голосов
/ 22 мая 2018

Прежде всего, если вы собираетесь создать HashMap, ваш класс ключей (NameAndAge) должен переопределить equals и hashCode().

Во-вторых, чтобыЭффективно, я предлагаю вам сначала создать Map<String,NameAndSalary> из второго List:

Map<String,NameAndSalary> helper =
    nameAndSalaryList.stream()
                     .collect(Collectors.toMap(NameAndSalary::getName,
                                               Function.identity()));

Наконец, вы можете создать Map, который вы хотите:

Map<NameAndAge,NameAndSalary> output = 
    nameAndAgeList.stream()
                  .collect(Collectors.toMap(Function.identity(),
                                            naa->helper.get(naa.getName())));
...