我有一个对象列表,说List<Type1>
是我使用type
进行分组的。(使用groupingBy)
现在,我想将Map>转换为同时具有该组的列表和ID的Type2。
class Type1{
int id;
int type;
String name;
}
class Type2{
int type;
List<Type1> type1List;
}
这是我为实现此目的而写的:
myCustomList
.stream()
.collect(groupingBy(Type1::getType))
.entrySet()
.stream()
.map(type1Item -> new Type2() {
{
setType(type1Item.getKey());
setType1List(type1Item.getValue());
}
})
.collect(Collectors.toList());
这很好用。但是我正在尝试使代码更加简洁。有没有一种方法可以避免这种情况再次发生,并使用某种平面图来实现。
答案 0 :(得分:2)
您可以将整理器功能传递给collectingAndThen
,以在形成初始map
之后完成工作。
List<Type2> result = myCustomList.stream()
.collect(Collectors.collectingAndThen(Collectors.groupingBy(Type1::getType),
m -> m.entrySet().stream()
.map(e -> new Type2(e.getKey(), e.getValue()))
.collect(Collectors.toList())));
答案 1 :(得分:1)
您应为Type2
提供以下形式的构造函数
Type2(int type, List<Type1> type1List) {
this.type = type;
this.type1List = type1List;
}
然后,您可以写.map(type1Item -> new Type2(type1Item.getKey(), type1Item.getValue()))
代替
.map(type1Item -> new Type2() {
{
setType(type1Item.getKey());
setType1List(type1Item.getValue());
}
})
另请参见What is Double Brace initialization in Java?
简而言之,这会造成内存泄漏,因为它会创建Type2
的子类,从而捕获type1Item
的整个生命周期。
但是您可以作为groupingBy
下游收集器的一部分执行转换。这意味着您必须使toList
明确,以便通过collectingAndThen
将其与随后的映射结合起来:
Collection<Type2> collect = myCustomList
.stream()
.collect(groupingBy(Type1::getType,
collectingAndThen(toList(), l -> new Type2(l.get(0).getType(), l))))
.values();
如果您确实需要List
,则可以使用
List<Type2> collect = myCustomList
.stream()
.collect(collectingAndThen(groupingBy(Type1::getType,
collectingAndThen(toList(), l -> new Type2(l.get(0).getType(), l))),
m -> new ArrayList<>(m.values())));
答案 2 :(得分:0)
您可以执行以下操作:
type1.map( type1Item -> new Type2(
type1Item.getKey(), type1Item
)).collect(Collectors.toList());