Java 8 группировать и добавлять к набору

#java #collections #java-8 #group-by #collectors

#java #Коллекции #java-8 #группировка по #сборщики

Вопрос:

У меня есть функция, которая возвращает Map<String, Set<String>> код, предшествующий java 8:

 Map<String, Set<String>> degreeMap = new HashMap<>();
for(Course  course : courses){
    Set<String> cList = degreeMap.get(course.getCourseLevel().toString());
    if(Objects.nonNull(cList)){
        cList.addAll(course.getMasterDegree()); //this is what i want to append to the old set
        degreeMap.put(course.getCourseLevel().toString(), cList);
    } else{
        degreeMap.put(course.getCourseLevel().toString(), new HashSet<>(course.getMasterDegree()));
    }
} 
return degreeMap;
  

Которые возвращают карту courselevel -> набор степеней.

Например, он считывает все курсы и возвращает карту типа:

 {"undergraduate" : ["BTech", "BSc", "BE"],
"masters": ["MTech", "MBA"],
"Executive": ["PGDBM", "EECP"]}
  

Вот мой класс курса:

 public class Course {
    private List<String> masterDegree;
    private CourseLevel courseLevel;
}
  

Но я хочу написать этот фрагмент кода в стиле Java 8. Для этого я попробовал это:

 Map<String, Set<String>> degreeMap = courses.stream().collect(
        Collectors.groupingBy(c -> c.getCourseLevel().toString(),
                Collectors.mapping(c -> c.getMasterDegree(), Collectors.toSet()))
);
  

который не работает, и я получаю следующую ошибку времени компиляции по этому поводу:

не существует экземпляров переменных типа, чтобы список соответствовал строке переменная вывода T имеет несовместимые границы: ограничения равенства: Строка нижние границы: Список

Любое предложение, как этого добиться?

Комментарии:

1. Мне кажется, что вы ищете flatMapping эквивалент Java-9 в более старой версии.

2. @GhostCat попытался отредактировать вопрос, чтобы он был достаточно актуальным. надеюсь, теперь все ясно.

3. @Naman спасибо за разрешение этой битвы: P

4. for(Course course : courses) degreeMap.computeIfAbsent(course.getCourseLevel() .toString(), x -> new HashSet<>()) .addAll(course.getMasterDegree()); Кстати, даже в вашей версии до Java 8 никогда не было причины для того, чтобы put тот же список Map снова появлялся после addAll .

Ответ №1:

Не проверено, но похоже, вы ищете что-то вроде:

     return courses.stream()
            .collect(Collectors.toMap(course -> course.getCourseLevel().toString(),
                    course -> new HashSet<>(course.getMasterDegree()),
                    (set1, set2) -> Stream.of(set1, set2)
                            .flatMap(Set::stream).collect(Collectors.toSet())));
  

Комментарии:

1. В этом случае, (set1, set2) -> { set1.addAll(set2); return set1; } очевидно, является предпочтительной функцией слияния…

Ответ №2:

Возможно, вас заинтересует метод Collectors.toMap() .

Вот пример, который вам может понадобиться настроить, поскольку я его не тестировал.

 Map<String, Set<String>> degreeMap = courses.stream()
    .collect(
        Collectors.toMap(
            item -> item.getCourseLevel().toString(), //your key mapping
            item -> item.getMasterDegree(), //your value mapping
            (oldValue, newValue) -> { //your process of aggregation
                if (null == oldValue) {
                    return newValue;
                } else {
                    oldValue.addAll(newValue);
                    return oldValue;
                }
            },
            LinkedHashMap::new //your result initialiser
        )
    );
  

Кроме того, еще один совет: вам не нужно получать по ключу и проверять наличие null, вы можете использовать методы .compute() , .computeIfAbsent() , .computeIfPresent() на карте

Ответ №3:

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

         // supposed to be initialied with non-empty values
        // Map<String, Set<String>> degreeMap = ...

        for(Course  course : courses){
            // something like below
            String key = course.getCourseLevel().toString();
            // degreeSet should not be null
            Set<String> degreeSet = course.getMasterDegree();

            // TODO: check nullable
            degreeSet.putAll(degreeMap.get(key));

            degreeMap.put(key, degreeSet);
        } 

        return degreeMap;