如何通过Java Stream生成自定义对象数组?现有实现优化咨询
Stream版本优化方案
首先需要修复原代码的隐藏bug:buildAttrib1和buildAttrib2方法参数均为Object obj,但反射调用时都误用了未通过参数传递的requestObject,属于复制粘贴错误,优化时首先要修正为使用传入的obj参数。
核心优化方向
- 提取公共异常处理逻辑:把反射获取方法、调用方法取值的重复异常逻辑抽成独立工具方法,避免Stream内部嵌套大量try-catch块,降低代码冗余
- 规避空指针风险:原实现如果找不到对应get方法会导致
method为null,后续调用invoke直接抛出空指针,优化后可通过Optional处理无效取值场景,避免NPE同时支持过滤无效字段 - 简化Stream链路结构:移除不必要的临时变量,让每一步操作语义清晰可读
优化后完整代码
import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Optional; import java.util.AbstractMap; public class MyClass { private Attrib[] buildAttrib2(Object obj) { Field[] fields = obj.getClass().getDeclaredFields(); return Arrays.stream(fields) // 关联字段名和对应取值,用SimpleEntry存储键值对无需额外自定义类 .map(f -> new AbstractMap.SimpleEntry<>( f.getName(), getFieldValue(obj, f) )) // 过滤掉取值失败的字段,若业务要求保留所有字段可移除该步骤 .filter(entry -> entry.getValue().isPresent()) // 构造Attrib对象 .map(entry -> new Attrib( entry.getKey(), new AttribVal[]{new AttribVal(entry.getValue().get())} )) .toArray(Attrib[]::new); } // 独立的反射取值工具方法,统一处理所有异常 private Optional<String> getFieldValue(Object obj, Field field) { String methodName = "get" + StringUtils.capitalize(field.getName()); try { Method method = obj.getClass().getMethod(methodName); return Optional.ofNullable((String) method.invoke(obj)); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { // 可根据业务需求调整异常处理逻辑,比如替换为日志打印、抛出业务运行时异常等 e.printStackTrace(); return Optional.empty(); } } }
补充说明
如果业务要求必须保留所有字段对应的Attrib,即使取值失败也返回values为空数组的Attrib,可以去掉filter步骤,直接在map中判断Optional是否有值,灵活调整构造逻辑即可。
内容的提问来源于stack exchange,提问作者user5245796
相关产品推荐
相关产品推荐

