I have an object called RawCarEnumData
having 3 enums:
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:
public class CarEnumData {
private BrandEnum brand;
private ModelEnum model;
private List<ColorEnum> colors;
//getters, setters, constructors
}
Now I have a list of RawCarEnumData
objects:
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))
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. 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. 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
. 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. The second argument to Collectors.groupingBy
is a downstream collector of that list. Here mapping
maps each value to a CarEnumData
with just a single color. 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()
. Finally I can pick out the values()
of the map which is the desired collection.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.