Java 8 Группировка и добавление в набор - PullRequest
2 голосов
/ 12 апреля 2019

У меня есть функция, которая возвращает 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;

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

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

{"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()))
);

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

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

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

Ответы [ 3 ]

3 голосов
/ 12 апреля 2019

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

    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())));
0 голосов
/ 12 апреля 2019

Возможно, вас заинтересует метод 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
        )
    );

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

0 голосов
/ 12 апреля 2019

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

        // 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...