我正在使用java 8流和收集器来迭代集合。在操作结束时,我必须将流中包含的对象转换为相关的业务对象。并且这些业务对象具有1到多的关系。 以下是清楚的描述所使用的类。
第一个是Helper类,代表我将在我的流上收集的集合。
public class Helper{
private String a;
private String additionalA;
private String additionalB;
private String additionalC;
//constructor, setter, getter, equals, hashCode omitted.
}
Bean A是单一的bean没有关系,只是原语。
public class BeanA{
private String a;
private String additionalA;
//constructor, setter, getter, equals, hashCode omitted.
}
Bean B与Bean A以及其他信息有1对多的关系
public class BeanB{
private List<BeanA> beanA = new ArrayList<BeanA>();
private String additonalB;
//constructor, setter, getter, equals, hashCode omitted.
}
BeanC与BeanB以及其他信息有1对多的关系
public static class BeanC {
private List<BeanB> beanB = new ArrayList<BeanB>();
private String additionalC;
//constructor, setter, getter, equals, hashCode omitted.
}
此外,我还有几种转换方法,例如:
public static BeanA getBeanA(Helper helper) {
BeanA a = new BeanA();
a.setA(helper.getA());
a.setAdditionalA(helper.getAdditionalA());
return a;
}
public static BeanB getBeanB(Helper helper) {
BeanB b = new BeanB();
//maybe wrong to add the data to list (see below)
b.getBeanA().add(getBeanA(helper));
b.setAdditonalB(helper.getAdditionalB());
return b;
}
public static BeanC getBeanC(Helper helper) {
BeanC c = new BeanC();
//maybe wrong to add the data to list (see below)
c.getBeanB().add(getBeanB(helper));
c.setAdditionalC(helper.getAdditionalC());
return c;
}
,预期结果是地图
Map<BeanC,Map<BeanB,List<BeanA>>>
我有 用于产生所需结果的以下块:
Map<BeanC, Map<BeanB, List<BeanA>>> res = helpers.stream()
.collect(Collectors.groupingBy(
Test::getBeanC,
Collectors.groupingBy(Test::getBeanB,
Collectors.collectingAndThen(Collectors.toList(),
list -> list.stream()
.map(Test::getBeanA)
.collect(Collectors.toList())))));
问题是BeanC和BeanB上的列表设置不正确。
任何人都知道如何使用收集器实现初始化1到多个关系?
答案 0 :(得分:0)
您无法使用分组功能填充集合。针对每个流元素(即Helper
实例)评估分组函数,以基于结果的相等来构建组。您的getBeanC
和getBeanB
方法每次创建一个新bean ,填充一个嵌套对象,在检查相等性后,为每个组删除其中一个对象
您的问题没有显示,如何定义这些bean的相等性,但考虑到additionalC
和additionalB
是唯一传递给它们的数据,我假设这些属性确定了相等。因此,在将组转换为bean实例之前,应首先按这些属性对Helper
实例进行分组,即
Map<String, Map<String, List<Helper>>> tmp = helpers.stream()
.collect(Collectors.groupingBy(Helper::getAdditionalC,
Collectors.groupingBy(Helper::getAdditionalB)));
现在,要将它们转换为bean实例,调整工厂方法会很有帮助:
public static BeanB getBeanB(String bId, List<Helper> beanA) {
BeanB b = new BeanB();
b.getBeanA().addAll(beanA.stream().map(Test::getBeanA).collect(Collectors.toList()));
b.setAdditonalB(bId);
return b;
}
public static BeanC getBeanC(String cId, Map<String,List<Helper>> beanB) {
BeanC c = new BeanC();
c.getBeanB().addAll(beanB.entrySet().stream()
.map(e -> getBeanB(e.getKey(), e.getValue()))
.collect(Collectors.toList()));
c.setAdditionalC(cId);
return c;
}
(getBeanA
)保持不变。
然后,您可以将最终Map
构建为
Map<BeanC, Map<BeanB, List<BeanA>>> res = tmp.entrySet().stream()
.map(e -> Test.getBeanC(e.getKey(), e.getValue()))
.collect(Collectors.toMap(Function.identity(),
c -> c.getBeanB().stream()
.collect(Collectors.toMap(Function.identity(), BeanB::getBeanA))));
但是,考虑到所有bean都可以通过BeanC
实例访问,您很可能不需要Map
,它只是分组操作的工件。因此,您只需收集到List<BeanC>
代替:
List<BeanC> list = tmp.entrySet().stream()
.map(e -> Test.getBeanC(e.getKey(), e.getValue()))
.collect(Collectors.toList());