【发布时间】:2020-09-10 21:02:25
【问题描述】:
首先,让我添加实际的“示例代码”:
Map<CarBrand, List<Car>> allCarsAndBrands = new HashMap();
final String bmwBrandName = "BMW";
final String audiBrandName = "AUDI";
List<Car> bmwCars = new ArrayList();
bmwCars.add(new Car(CarType.FAST, "Z4", "silver", bmwBrandName));
bmwCars.add(new Car(CarType.FAST, "M3", "red", bmwBrandName));
bmwCars.add(new Car(CarType.SLOW, "X1", "black", bmwBrandName));
List<Car> audiCars = new ArrayList();
audiCars.add(new Car(CarType.FAST, "S3", "yellow", audiBrandName));
audiCars.add(new Car(CarType.FAST, "R8", "silver", audiBrandName));
audiCars.add(new Car(CarType.SLOW, "A1", "white", audiBrandName));
allCarsAndBrands.put(new CarBrand(bmwBrandName), bmwCars);
allCarsAndBrands.put(new CarBrand(audiBrandName), audiCars);
Map<CarType, Map<CarBrand, List<Car>>> mappedCars;
问题
我的目标是用CarType 填充mappedCars,这将产生两个大集合:一个包含所有 FAST 车,另一个包含 SLOW 车(或任何未来的“类型”,每个都有前一个带有CarBrand 和相关汽车的地图结构。
我目前无法为这个“在其他地图中包含列表的地图”找到正确使用集合/流。我遇到过其他简单地图/列表的案例,但事实证明这个案例对我来说更棘手。
尝试
这是一个初始代码“尝试”:
mappedCars = allCarsAndBrands.entrySet()
.stream()
.collect(
groupingBy(Car::getType,
groupingBy(Map.Entry::getKey)
)
);
我也收到“非静态无法引用错误”(Map.Entry::getKey),但这是因为我未能匹配实际的预期回报(Static context cannot access non-static in Collectors)
此时我只是感到困惑,也尝试使用Collectors.toMap,但仍然无法获得工作分组。
附加内容
以下是此示例的类定义:
class CarBrand {
CarBrand(String name) {
this.name = name;
}
String name;
}
class Car {
Car(CarType type, String name, String color, String brandName) {
this.type = type;
this.name = name;
this.color = color;
this.brandName = brandName;
}
public CarType getType() {
return type;
}
CarType type;
String name;
String color;
String brandName;
}
enum CarType {
FAST,
SLOW,
}
编辑:“脏”解决方案
这是一个“hackish”解决方案(基于 cmets 的建议,将检查答案!):
Map<CarType, Map<CarBrand, List<Car>>> mappedCars = allCarsAndBrands
.values()
.stream()
.flatMap(List::stream)
.collect(Collectors.groupingBy(
Car::getType,
Collectors.groupingBy(
car -> allCarsAndBrands.keySet().stream().filter(brand -> brand.name == car.brandName).findFirst().get(),
Collectors.toList()
)
));
正如 cmets 中提到的(之前应该在此处添加),有一个“业务约束”为解决方案增加了一些限制。我也不想创建一个新的CarBrand,因为在现实世界中,这并不像在此看到的那么简单......但同样,使用原始地图和过滤 + 查找实在是太糟糕了。
【问题讨论】:
-
A
Car知道它的“型号”但不知道它的“品牌”(“品牌”)?你应该先解决这个问题。 -
现在您在
Car对象中有品牌,这很容易:allCarsAndBrands.values().stream().flatMap(List::stream).collect(Collectors.groupingBy(Car::getType, Collectors.groupingBy(Car::getBrand, Collectors.toList()))) -
我不明白:你想要所有 FAST 和 SLOW 车,而不关心品牌,不是吗?
Stream.concat(bmwCars, audiCars).collect(groupingBy(Car::getCarType))够吗? -
当然,如果你不想把它放在它所属的
Car中,创建一个Map<String, CarBrand>并查找它。我没有看到问题。
标签: java java-8 java-stream method-reference collect