簡體   English   中英

如何 map 多個具有兩個相同值和一個不同值的對象與一個 object 以及這些不同值的列表?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM