Collectors.groupingBy для внутреннего поля необязательного поля

#java #java-stream

#java #java-поток

Вопрос:

Я хотел бы отобразить поток Stream<Car> на карту, например, Map<String, List<Car<StudentInGroup>>> где Car класс выглядит следующим образом:

 public class Car<T> {
    Optional<T> studentInGroup;
    public Car()
    {  
    }

    public Optional<T> getStudentInGroup() {
        return studentInGroup;
    }

    public void setStudentInGroup(T studentInGroup) {
        this.studentInGroup=Optional.of(studentInGroup);
    }
}
  

и StudentInGroup похоже

 public class StudentInGroup {
    private String name;
    private boolean isGirl;
    private int age;
}
  

итак, я хотел бы создать карту на основе поля name StudenInGroup , его Optional<StudentInGroup> внутри Car нет Optional.empty() , в то время как я хотел бы заменить его на «none», если в конкретном cat поле studentIngroup равно Optional.empty() .

 Map<String, List<Car<StudentInGroup>>> stringStudentInGroupMap38= studentInGroupStreamSupplier.get().map((StudentInGroup studentInGroup)->{Car<StudentInGroup> car=new Car<StudentInGroup>();car.setStudentInGroup(studentInGroup);return car;}).collect(Collectors.groupingBy(car->car.getStudentInGroup().orElseGet(... do something with student there).getName())
  

Возможным решением является создание «none containing StudentInGroup», чье getName вернет нужные данные, хотя это не похоже на правильный подход. однако <Я не нашел никакого способа сохранить оригинал Stream<Car> без сопоставления его с некоторыми другими потоками и принудительной группировки в Car.StudentInGroup.Имя или «нет», если Optional<StudenInGroup> оно пустое. Приветствуются любые предложения по его кодированию, понятному и читабельному!

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

1. Stream<Car> является необработанным типом. Разве это не должно быть Stream<Car<StudentInGroup>> ?

2. Если это так, просто сделайте cars.stream().collect(Collectors.groupingBy(car -> car.getStudentInGroup().map(s -> s.getName()).orElse("none")))

3. фильтр @Deadpool не будет работать, поскольку я бы хотел, чтобы пустые опции также были включены в карту

4. @shmosel хорошая идея

5. @shmosel пожалуйста, опубликуйте свой ответ в качестве официального ответа, у меня это сработало!

Ответ №1:

Просто используйте groupingBy() collector и сопоставьте Optional , чтобы получить ключ:

 Map<String, List<Car<StudentInGroup>>> byName = cars.stream()
        .collect(Collectors.groupingBy(
                car -> car.getStudentInGroup()
                        .map(s -> s.getName())
                        .orElse("none")))