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

I have an object called RawCarEnumData having 3 enums:我有一个名为 RawCarEnumData 的RawCarEnumData有 3 个枚举:

public class RawCarEnumData {

    private BrandEnum brand;
    private ModelEnum model;
    private ColorEnum color;

    //getters, setters, constructors

}

and an object CarEnumData having 2 enums and a list of enums:和一个 object CarEnumData有 2 个枚举和一个枚举列表:

public class CarEnumData {

    private BrandEnum brand;
    private ModelEnum model;
    private List<ColorEnum> colors;

    //getters, setters, constructors

}

Now I have a list of RawCarEnumData objects:现在我有一个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: 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))

I have tried a few things but without success.我尝试了几件事,但没有成功。 How can this be achieved?如何做到这一点? Is this even possible?这甚至可能吗?

I know this is a Java question but I like to provide a Kotlin answer.我知道这是一个 Java 问题,但我想提供一个 Kotlin 答案。 It might help you come up with a Java solution or you might even want to include the Kotlin solution in your project since it should be interoperable with Java.它可能会帮助您提出 Java 解决方案,或者您甚至可能希望在您的项目中包含 Kotlin 解决方案,因为它应该与 Java 互操作。 The following code seems to do what you would like:以下代码似乎可以满足您的需求:

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 }

So what you want to do is to group your RawCarEnumData s by brand and model, and then reduce each list of RawCarEnumData s into one CarEnumData .因此,您要做的是将RawCarEnumData按品牌和 model 分组,然后CarEnumData RawCarEnumData的每个列表减少为一个RawCarEnumData One way to do this would be the following:一种方法如下:

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();

Breaking it down, the Collectors.groupingBy gives you a map with keys given by applying a function, and a list of all values that corresponds to that key.分解它, Collectors.groupingBy为您提供 map,其中键是通过应用 function 给出的,以及与该键对应的所有值的列表。 The second argument to Collectors.groupingBy is a downstream collector of that list. Collectors.groupingBy的第二个参数是该列表的下游收集器。 Here mapping maps each value to a CarEnumData with just a single color.此处的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() . 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() The reducing collector returns an optional which is empty if there are no values in the stream, but in this case groupingBy guarantees me at least one value in every group, so I can safely retrieve the value with Optional.orElseThrow() .如果 stream 中没有值,则减少收集器返回一个为空的可选值,但在这种情况下, groupingBy保证每个组中至少有一个值,因此我可以使用Optional.orElseThrow()安全地检索该值。 Finally I can pick out the values() of the map which is the desired collection.最后,我可以挑选出所需的集合 map 的values()

You didn't mention which Java version you use, if using an older version you may have to use collect(Collectors.toList) and some other way to create the group key.您没有提到您使用哪个 Java 版本,如果使用旧版本,您可能必须使用collect(Collectors.toList)和其他一些方式来创建组密钥。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 按值按降序对哈希映射进行排序。 对一个键有两个不同的值 - Sort Hash map in descending order by value. Having two different values to one key 显示一个类的两个对象的不同值 - Show different values two objects of one class 将两个对象列表合并到Map中,值与Java 8中的不同对象相同 - Merge two lists of objects into Map having value as different object in java 8 多个微调器使用一个具有不同值的列表 - Multiple spinners using one list with different values 如何将不同对象的 ArrayList 组合到一个列表 / Map 中,然后从组合列表 /Map 中检索每个 arraylist 的值? - How to combine ArrayList of different objects into one list / Map and then retrive value of each arraylist from combined list /Map? 如何将一个列表中具有相同值的两个字段的对象合并为一个简化列表? - How can I combine objects with two fields having the same values in a list into one reduced list? 如何将值从一个列表复制到另一个具有不同对象的列表 - How to copy value from one list to another list having different objects 如何将两个不同的List对象合并到一个List中并对其进行排序 - how to merge two different List objects into one List and sort them 如何比较Java中两个不同列表中的Objects值? - How to compare Objects values which is inside two different list in Java? 生成两个相同的随机数,另一个不同 - Generating two identical random numbers and one that is different
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM