我有一个对象列表说我使用type
分组List<Type1>
.(使用分组依据( 现在我想将该 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());
这非常有效。但我正在努力使代码更加干净。有没有办法避免再次流式传输这个东西并使用某种平面图来实现这一点。
您可以将整理器函数传递给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())));
你应该给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());
}
})
参见 什么是 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())));
您可以执行以下操作:
type1.map( type1Item -> new Type2(
type1Item.getKey(), type1Item
)).collect(Collectors.toList());