Nhóm danh sách theo các phần tử của danh sách lồng nhau [trùng lặp]

Jan 25 2021

Tôi có đối tượng Xe với các tham số như:

private String model;
private BigDecimal price;
private Color color;
private BigDecimal milleage;
private List<String> components;

Tôi đã tạo danh sách các đối tượng Xe:

var cars = List.of(
    Car.create("FORD", BigDecimal.valueOf(120000), Color.RED, BigDecimal.valueOf(150000),
            List.of("AIR CONDITIONING", "VOICE SERVICE")),
    Car.create("FORD", BigDecimal.valueOf(160000), Color.RED, BigDecimal.valueOf(150000),
            List.of("AIR CONDITIONING", "VOICE SERVICE")),
    Car.create("AUDI", BigDecimal.valueOf(200000), Color.BLACK, BigDecimal.valueOf(195000),
            List.of("NAVIGATION", "AUTOMATIC GEARBOX")),
    Car.create("FIAT", BigDecimal.valueOf(70000), Color.BLUE, BigDecimal.valueOf(85000),
            List.of("AIR CONDITIONING", "MANUAL GEARBOX")));

Bây giờ tôi muốn tạo Map<String, List<Car>>nơi chuỗi là phần tử của danh sách thành phần và List<Car>>là danh sách các Carđối tượng chứa thành phần này.

Tôi đã thử một cái gì đó như thế này dựa trên một số vấn đề tương tự nhưng thực sự không biết làm thế nào để giải quyết vấn đề này:

static Map<String, List<Car>> carsThatGotComponent(List<Car> cars) {
    return cars.stream()
               .flatMap(car -> car.getComponents()
                       .stream()
                       .map(component -> new AbstractMap.SimpleEntry<>(car, component)))
               .collect(Collectors.groupingBy(
                        Map.Entry::getValue,
                        Collectors.mapping(Map.Entry::getKey, Map.Entry::getValue)));
}

Trả lời

2 NikolasCharalambidis Jan 25 2021 at 19:15

Collectors#mappingyêu cầu dưới dạng tham số thứ hai là một hàm hạ lưu Collector, không phải một hàm ánh xạ.

public static <T,U,A,R> Collector<T,?,R> mapping(
    Function<? super T,? extends U> mapper, 
    Collector<? super U,A,R> downstream)

Bạn muốn sử dụng Collectors.toList()thay thế:

return cars.stream()
    .flatMap(car -> car.getComponents()
                       .stream()
                       .map(component -> new AbstractMap.SimpleEntry<>(car, component)))
    .collect(Collectors.groupingBy(
            AbstractMap.SimpleEntry::getValue,
            Collectors.mapping(AbstractMap.SimpleEntry::getKey, Collectors.toList())));

Chừng nào bạn sử dụng java-10 hoặc mới hơn, bạn có thể sử dụng đơn giản hóa toàn bộ Suối thành một nhà sưu tập sử dụng Collectors#flatMappingnhư của java-9 :

return cars.stream()
    .collect(Collectors.flatMapping(
             car -> car.getComponents()
                       .stream()
                       .map(component -> new AbstractMap.SimpleEntry<>(car, component)),
             Collectors.groupingBy(AbstractMap.SimpleEntry::getValue,
                     Collectors.mapping(AbstractMap.SimpleEntry::getKey, 
                             Collectors.toList()))));