如何使用Java 8 Streams对对象属性进行分组并映射到另一个对象? [英] How to groupBy object properties and map to another object using Java 8 Streams?
问题描述
假设我有一组碰碰车,它们的侧面有大小,颜色和标识(汽车代码").
Suppose I have a group of bumper cars, which have a size, a color and an identifier ("car code") on their sides.
class BumperCar {
int size;
String color;
String carCode;
}
现在,我需要将碰碰车映射到DistGroup
对象的List
,每个对象都包含属性size
,color
和汽车代码的List
.
Now I need to map the bumper cars to a List
of DistGroup
objects, which each contains the properties size
, color
and a List
of car codes.
class DistGroup {
int size;
Color color;
List<String> carCodes;
void addCarCodes(List<String> carCodes) {
this.carCodes.addAll(carCodes);
}
}
例如,
[
BumperCar(size=3, color=yellow, carCode=Q4M),
BumperCar(size=3, color=yellow, carCode=T5A),
BumperCar(size=3, color=red, carCode=6NR)
]
应导致:
[
DistGroup(size=3, color=yellow, carCodes=[ Q4M, T5A ]),
DistGroup(size=3, color=red, carCodes=[ 6NR ])
]
我尝试了以下操作,实际上可以完成我想要的操作.但是问题在于,它实现了即时结果(生成为Map
),而且我还认为可以一次完成(也许使用mapping
或collectingAndThen
或reducing
之类的方法),从而使结果更加优雅代码.
I tried the following, which actually does what I want it to do. But the problem is that it materializes the immediate result (into a Map
) and I also think that it can be done at once (perhaps using mapping
or collectingAndThen
or reducing
or something), resulting in more elegant code.
List<BumperCar> bumperCars = ...
Map<SizeColorCombination, List<BumperCar>> map = bumperCars.stream()
.collect(groupingBy(t -> new SizeColorCombination(t.getSize(), t.getColor())));
List<DistGroup> distGroups = map.entrySet().stream()
.map(t -> {
DistGroup d = new DistGroup(t.getKey().getSize(), t.getKey().getColor());
d.addCarCodes(t.getValue().stream()
.map(BumperCar::getCarCode)
.collect(toList()));
return d;
})
.collect(toList());
如何在不使用变量的情况下立即获得期望的结果?
How can I get the desired result without using a variable for an immediate result?
编辑:如何在不实现即时结果的情况下获得期望的结果?我只是在寻找一种不会实现立即结果的方法,至少不会在表面上实现.这意味着我不想使用这样的东西:
How can I get the desired result without materializing the immediate result? I am merely looking for a way which does not materialize the immediate result, at least not on the surface. That means that I prefer not to use something like this:
something.stream()
.collect(...) // Materializing
.stream()
.collect(...); // Materializing second time
当然,如果可能的话.
请注意,为简洁起见,我省略了getter和构造函数.您可能还假定equals
和hashCode
方法已正确实现.另请注意,我正在使用SizeColorCombination
用作分组依据密钥.此类显然包含属性size
和color
.也可以使用类似Tuple
或Pair
的类,或表示两个任意值的组合的任何其他类.
编辑:还请注意,可以使用ol's skool for loop代替课程,但这不在此问题的范围内.
Note that I omitted getters and constructors for brevity. You may also assume that equals
and hashCode
methods are properly implemented. Also note that I'm using the SizeColorCombination
which I use as group-by key. This class obviously contains the properties size
and color
. Classes like Tuple
or Pair
or any other class representing a combination of two arbitrary values may also be used.
Edit: Also note that an ol' skool for loop can be used instead of course, but that is not in the scope of this question.
推荐答案
如果我们假设DistGroup
具有基于size
和color
的hashCode/equals
,则可以这样:
If we assume that DistGroup
has hashCode/equals
based on size
and color
, you could do it like this:
bumperCars
.stream()
.map(x -> {
List<String> list = new ArrayList<>();
list.add(x.getCarCode());
return new SimpleEntry<>(x, list);
})
.map(x -> new DistGroup(x.getKey().getSize(), x.getKey().getColor(), x.getValue()))
.collect(Collectors.toMap(
Function.identity(),
Function.identity(),
(left, right) -> {
left.getCarCodes().addAll(right.getCarCodes());
return left;
}))
.values(); // Collection<DistGroup>
这篇关于如何使用Java 8 Streams对对象属性进行分组并映射到另一个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!