如何将Java中同number的SampleObject对象合并为一个?
合并相同Number的SampleObject对象问题解决
问题场景
现有SampleObject类,包含number、valueOne、valueTwo、valueThree属性:
- 每个对象的
number非空 - 每个对象仅一个value字段(valueOne/valueTwo/valueThree)非空
AnotherClass类包含该对象的列表,需要将列表中相同number的SampleObject合并为一个对象,最终生成以number为键、合并后对象为值的Map。
示例
原对象列表:
- Sample1(number:"1", valueOne="1", valueTwo=null, valueThree=null)
- Sample2(number:"1", valueOne=null, valueTwo="2", valueThree=null)
- Sample3(number:"1", valueOne=null, valueTwo=null, valueThree="3")
- Sample4(number:"2", valueOne="5", valueTwo=null, valueThree=null)
期望合并结果:
- Sample1Merged(number:"1", valueOne="1", valueTwo="2", valueThree="3")
- Sample4(number:"2", valueOne="5", valueTwo=null, valueThree=null)
现有问题
当前代码使用forEach直接向Map中put对象,遇到相同number时会直接覆盖已有对象,无法实现属性合并:
final Map<String, SampleObject> mapOfMergedSamples = new LinkedHashMap<>(); anotherClass.getSampleObjects().stream() .sorted(Comparator.comparing(SampleObject::getNumber)) .forEach(s -> mapOfMergedSamples.put(s.getNumber(), new SampleObject(Stream.of(s.getValueOne(), s.getValueTwo()) .filter(Objects::nonNull) .collect(Collectors.joining()), s.getValueThree())) ); return mapOfMergedSamples;
解决方案
使用Stream.collect()结合Collectors.toMap(),通过指定合并函数处理重复键的对象,实现属性合并而非覆盖。
代码实现
final Map<String, SampleObject> mapOfMergedSamples = anotherClass.getSampleObjects() .stream() .collect(Collectors.toMap( // 提取number作为Map的键 SampleObject::getNumber, // 初始值为当前对象 sample -> sample, // 合并相同number的两个对象 (existingSample, newSample) -> { // 逐个合并value属性:优先保留已有对象的非空值,否则取新对象的值 String mergedValueOne = existingSample.getValueOne() != null ? existingSample.getValueOne() : newSample.getValueOne(); String mergedValueTwo = existingSample.getValueTwo() != null ? existingSample.getValueTwo() : newSample.getValueTwo(); String mergedValueThree = existingSample.getValueThree() != null ? existingSample.getValueThree() : newSample.getValueThree(); // 返回合并后的新SampleObject对象(需匹配你的类构造方法参数) return new SampleObject(existingSample.getNumber(), mergedValueOne, mergedValueTwo, mergedValueThree); }, // 指定用LinkedHashMap保持原列表顺序(可选,和你原代码一致) LinkedHashMap::new )); return mapOfMergedSamples;
关键逻辑说明
Collectors.toMap的合并函数:
当遇到相同number的对象时,该函数会将已有对象(existingSample)和新对象(newSample)的非空value属性进行合并。由于题目中每个原对象仅一个非空value,因此直接取两边的非空值即可完成合并。- 保持顺序:
最后一个参数LinkedHashMap::new确保合并后的Map和原列表的顺序一致,和你原代码的LinkedHashMap逻辑匹配,可根据需求选择是否保留。 - 构造方法适配:
注意代码中的new SampleObject(...)需要匹配你实际的SampleObject类构造方法参数,确保参数顺序和数量正确。
简化写法(可选)
如果你的SampleObject类支持Builder模式,合并逻辑可以更简洁:
(existing, newSample) -> new SampleObject.Builder() .number(existing.getNumber()) .valueOne(Optional.ofNullable(existing.getValueOne()).orElse(newSample.getValueOne())) .valueTwo(Optional.ofNullable(existing.getValueTwo()).orElse(newSample.getValueTwo())) .valueThree(Optional.ofNullable(existing.getValueThree()).orElse(newSample.getValueThree())) .build()
内容的提问来源于stack exchange,提问作者noob123
相关产品推荐
相关产品推荐

