Не совсем то, что вы просили, но вот компактный способ выполнить то, что вы хотите, просто для полноты:
Map<String, StudentResponse> map = new LinkedHashMap<>();
students.forEach(s -> map.computeIfAbsent(
s.getCourse(),
k -> new StudentResponse(s.getCourse()))
.getStudents().add(s));
Это предполагает, что StudentResponse
имеет конструктор, который принимает курс в качестве аргументаи получатель для списка студентов, и что этот список является изменяемым (т.е. ArrayList
), так что мы можем добавить к нему текущего студента.
Хотя вышеуказанный подход работает, он явно нарушает фундаментальный принцип ООинкапсуляция.Если вы в порядке с этим, то все готово.Если вы хотите соблюдать инкапсуляцию, вы можете добавить метод к StudentResponse
, чтобы добавить Student
экземпляр:
public void addStudent(Student s) {
students.add(s);
}
Тогда решение будет иметь вид:
Map<String, StudentResponse> map = new LinkedHashMap<>();
students.forEach(s -> map.computeIfAbsent(
s.getCourse(),
k -> new StudentResponse(s.getCourse()))
.addStudent(s));
Это решение явно лучше предыдущего и позволит избежать отказа от серьезного рецензента кода.
Оба решения основаны на Map.computeIfAbsent
, который либо возвращает StudentResponse
для предоставленного курса (если существуетзапись для этого курса на карте), либо создает и возвращает StudentResponse
экземпляр, созданный с курсом в качестве аргумента.Затем ученик добавляется во внутренний список учеников возвращенных StudentResponse
.
Наконец, ваши StudentResponse
экземпляры находятся в значениях карты:
Collection<StudentResponse> result = map.values();
Если вынужен List
вместо Collection
:
List<StudentResponse> result = new ArrayList<>(map.values());
Примечание: я использую LinkedHashMap
вместо HashMap
, чтобы сохранить порядок вставки, то есть порядок студентов в оригиналесписок.Если у вас нет таких требований, просто используйте HashMap
.