繁体   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