按嵌套列表的元素对列表进行分组
Group list by elements of nested list
我有 Car 对象,其参数如下:
private String model;
private BigDecimal price;
private Color color;
private BigDecimal milleage;
private List<String> components;
我创建了汽车对象列表:
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")));
现在我想创建 Map<String, List<Car>>
,其中字符串是组件列表的元素,List<Car>>
是包含该组件的 Car
个对象的列表。
我根据一些类似的问题尝试过类似的方法,但真的不知道如何解决这个问题:
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)));
}
Collectors#mapping
需要下游 Collector
作为第二个参数,而不是映射函数。
public static <T,U,A,R> Collector<T,?,R> mapping(
Function<? super T,? extends U> mapper,
Collector<? super U,A,R> downstream)
您想改用 Collectors.toList()
:
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())));
只要你用java-10 or later, you can use simplify the whole Stream into one collector using Collectors#flatMapping
as of 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()))));
我有 Car 对象,其参数如下:
private String model;
private BigDecimal price;
private Color color;
private BigDecimal milleage;
private List<String> components;
我创建了汽车对象列表:
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")));
现在我想创建 Map<String, List<Car>>
,其中字符串是组件列表的元素,List<Car>>
是包含该组件的 Car
个对象的列表。
我根据一些类似的问题尝试过类似的方法,但真的不知道如何解决这个问题:
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)));
}
Collectors#mapping
需要下游 Collector
作为第二个参数,而不是映射函数。
public static <T,U,A,R> Collector<T,?,R> mapping( Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream)
您想改用 Collectors.toList()
:
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())));
只要你用java-10 or later, you can use simplify the whole Stream into one collector using Collectors#flatMapping
as of 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()))));