[英]Sort Hash map in descending order by value. Having two different values to one key
[英]How to map multiple objects having two identical values and one different value to one object with list of those different values?
我有一个名为 RawCarEnumData 的RawCarEnumData
有 3 个枚举:
public class RawCarEnumData {
private BrandEnum brand;
private ModelEnum model;
private ColorEnum color;
//getters, setters, constructors
}
和一个 object CarEnumData
有 2 个枚举和一个枚举列表:
public class CarEnumData {
private BrandEnum brand;
private ModelEnum model;
private List<ColorEnum> colors;
//getters, setters, constructors
}
现在我有一个RawCarEnumData
对象列表:
List<RawCarEnumData> rawCarEnumDataList = List.of(
new RawCarEnumData(BrandEnum.FORD, ModelEnum.FIESTA, ColorEnum.RED),
new RawCarEnumData(BrandEnum.FORD, ModelEnum.FIESTA, ColorEnum.BLUE),
new RawCarEnumData(BrandEnum.FORD, ModelEnum.FIESTA, ColorEnum.YELLOW),
new RawCarEnumData(BrandEnum.FORD, ModelEnum.FOCUS, ColorEnum.YELLOW)
}
Now I want to use stream API to map the List<RawCarEnumData>
to List<CarEnumData>
so the final output will look like this:
List<CarEnumData> carEnumData:
- CarEnumData(BrandEnum.FORD, ModelEnum.FIESTA, List.of(ColorEnum.RED, ColorEnum.BLUE, ColorEnum.YELLOW))
- CarEnumData(BrandEnum.FORD, ModelEnum.FOCUS, List.of(ColorEnum.YELLOW))
我尝试了几件事,但没有成功。 如何做到这一点? 这甚至可能吗?
我知道这是一个 Java 问题,但我想提供一个 Kotlin 答案。 它可能会帮助您提出 Java 解决方案,或者您甚至可能希望在您的项目中包含 Kotlin 解决方案,因为它应该与 Java 互操作。 以下代码似乎可以满足您的需求:
fun main() {
val rawCarEnumDataList = listOf(
RawCarEnumData(BrandEnum.FORD, ModelEnum.FIESTA, ColorEnum.RED),
RawCarEnumData(BrandEnum.FORD, ModelEnum.FIESTA, ColorEnum.BLUE),
RawCarEnumData(BrandEnum.FORD, ModelEnum.FIESTA, ColorEnum.YELLOW),
RawCarEnumData(BrandEnum.FORD, ModelEnum.FOCUS, ColorEnum.YELLOW)
)
val carEnumData = rawCarEnumDataList
.groupBy { Pair(it.brand, it.model) }
.values.map { cars -> CarEnumData(cars.first().brand,cars.first().model, cars.map { it.color }.distinct()) }
print(carEnumData)
// prints [CarEnumData(brand=FORD, model=FIESTA, colors=[RED, BLUE, YELLOW]), CarEnumData(brand=FORD, model=FOCUS, colors=[YELLOW])]
}
data class RawCarEnumData(
val brand: BrandEnum,
val model: ModelEnum,
val color: ColorEnum
)
data class CarEnumData (
val brand: BrandEnum,
val model: ModelEnum,
val colors: List<ColorEnum>
)
enum class BrandEnum { FORD }
enum class ModelEnum { FIESTA, FOCUS }
enum class ColorEnum { RED, BLUE, YELLOW }
因此,您要做的是将RawCarEnumData按品牌和 model 分组,然后CarEnumData
RawCarEnumData
的每个列表减少为一个RawCarEnumData
。 一种方法如下:
final var result =
rawCarEnumDataList.stream()
.collect(
Collectors.groupingBy(
car -> Map.entry(car.brand, car.model),
Collectors.mapping(
car -> new CarEnumData(car.brand(), car.model(), List.of(car.color)),
Collectors.collectingAndThen(
Collectors.reducing(
(car1, car2) ->
new CarEnumData(
car1.brand(),
car2.model(),
Stream.concat(car1.colors.stream(), car2.colors.stream())
.toList())),
Optional::orElseThrow))))
.values();
分解它, Collectors.groupingBy
为您提供 map,其中键是通过应用 function 给出的,以及与该键对应的所有值的列表。 Collectors.groupingBy
的第二个参数是该列表的下游收集器。 此处的mapping
将每个值映射到仅具有一种颜色的CarEnumData
。 Collectors.mappingBy
also takes a downstream collector as a second argument, where I used Collectors.reducing
to merge all CarEnumData
s with the same brand and model into one, by merging the lists of colors with Stream.concat(car1.colors.stream(), car2.colors.stream()).toList()
。 如果 stream 中没有值,则减少收集器返回一个为空的可选值,但在这种情况下, groupingBy
保证每个组中至少有一个值,因此我可以使用Optional.orElseThrow()
安全地检索该值。 最后,我可以挑选出所需的集合 map 的values()
。
您没有提到您使用哪个 Java 版本,如果使用旧版本,您可能必须使用collect(Collectors.toList)
和其他一些方式来创建组密钥。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.