![](/img/trans.png)
[英]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.