Java按id分组将List<Object[]>转为List<MyBean>的Stream实现
Stream 实现方案
直接用Collectors.toMap完成分组聚合即可,不需要先生成分组的中间List,全程流式处理,也不需要给MyBean额外添加setter、无参构造,完全适配你最初定义的带Builder的类结构:
import java.util.*; import java.util.stream.Collectors; public class TestClass { public static void main(String[] args) { TestClass test = new TestClass(); List<Object[]> resultList = test.buildResultList(); List<MyBean> beans = new ArrayList<>(resultList.stream() .collect(Collectors.toMap( // 分组key:每行数据的id arr -> (Integer) arr[0], // 首次遇到某个id时,初始化MyBean对象 arr -> { Map<String, Object> initAttrs = new HashMap<>(); initAttrs.put((String) arr[2], arr[3]); return MyBean.builder() .id((Integer) arr[0]) .name((String) arr[1]) .customAttributes(initAttrs) .build(); }, // 同id的重复数据,直接把自定义属性合并到已存在的Bean中 (existBean, newBean) -> { existBean.getCustomAttributes().putAll(newBean.getCustomAttributes()); return existBean; }, // 如果需要保留id首次出现的顺序,解开下面这行注释即可 // LinkedHashMap::new )).values()); System.out.println(beans); } private List<Object[]> buildResultList() { List<Object[]> resultList = new ArrayList<>(); Object[] arr1 = new Object[4]; arr1[0] = 1; arr1[1] = "name 1"; arr1[2] = "custom_attr_1"; arr1[3] = "custom_attr_1_val_1"; resultList.add(arr1); Object[] arr2 = new Object[4]; arr2[0] = 1; arr2[1] = "name 1"; arr2[2] = "custom_attr_2"; arr2[3] = "custom_attr_2_val_1"; resultList.add(arr2); Object[] arr3 = new Object[4]; arr3[0] = 1; arr3[1] = "name 1"; arr3[2] = "custom_attr_3"; arr3[3] = "custom_attr_3_val_1"; resultList.add(arr3); Object[] arr4 = new Object[4]; arr4[0] = 2; arr4[1] = "name 2"; arr4[2] = "custom_attr_1"; arr4[3] = "custom_attr_1_val_2"; resultList.add(arr4); Object[] arr5 = new Object[4]; arr5[0] = 2; arr5[1] = "name 2"; arr5[2] = "custom_attr_2"; arr5[3] = "custom_attr_2_val_2"; resultList.add(arr5); Object[] arr6 = new Object[4]; arr6[0] = 2; arr6[1] = "name 2"; arr6[2] = "custom_attr_3"; arr6[3] = "custom_attr_3_val_2"; resultList.add(arr6); Object[] arr7 = new Object[4]; arr7[0] = 3; arr7[1] = "name 3"; arr7[2] = "custom_attr_1"; arr7[3] = "custom_attr_1_val_3"; resultList.add(arr7); Object[] arr8 = new Object[4]; arr8[0] = 3; arr8[1] = "name 3"; arr8[2] = "custom_attr_2"; arr8[3] = "custom_attr_2_val_3"; resultList.add(arr8); Object[] arr9 = new Object[4]; arr9[0] = 3; arr9[1] = "name 3"; arr9[2] = "custom_attr_3"; arr9[3] = "custom_attr_3_val_3"; resultList.add(arr9); return resultList; } } // 保留原MyBean定义即可,不需要额外加@Setter、@NoArgsConstructor @Getter @ToString @Builder(toBuilder = true) class MyBean { private Integer id; private String name; private Map<String, Object> customAttributes; // equals和hashCode方法基于id字段实现 }
方案对比原实现的优势
- 少了一次中间分组生成
Map<Integer, List<Object[]>>的过程,一次流收集就完成分组、对象构造、属性合并全流程,内存占用更低。 - 不需要修改原MyBean的类结构,不用强制添加setter、无参构造,不会破坏类的封装性。
- 去掉了循环内重复给name、customAttributes字段赋值的无效逻辑,合并属性直接复用Map的
putAll方法,代码更简洁。
提示:如果使用JDK9及以上版本,初始化自定义属性可以直接用
Map.of((String) arr[2], arr[3])替换逐行put的写法,代码会更精简。
内容的提问来源于stack exchange,提问作者curious_brain
相关产品推荐
相关产品推荐

