合并两个List并替换null值的高效实现方法问询
高效实现List合并:用非null值替换目标List的null项
需求说明
给定两个同长度的List<Integer>(注:Java中int基本类型无法存储null,实际应使用包装类型Integer):
List<Integer> A = Arrays.asList(1,1,1,null,null,null,null,null,null); List<Integer> B = Arrays.asList(null,null,null,2,2,2,null,null,null);
需要合并得到List C,规则为:用B中的非null值替换A中的null值,保留A中的非null值,最终结果:
List<Integer> C = Arrays.asList(1,1,1,2,2,2,null,null,null);
同时需支持类似[1,null,1,null]的交替null场景,且避免原双层循环的高性能开销。
高效实现方案
1. 单索引遍历(最优性能)
通过一次循环按索引一一处理两个List的元素,时间复杂度为O(n),远优于双层循环的O(n²)。
方式一:创建新List(不修改原数据)
import java.util.ArrayList; import java.util.List; public class ListMerger { public static List<Integer> mergeLists(List<Integer> A, List<Integer> B) { if (A.size() != B.size()) { throw new IllegalArgumentException("两个List必须保持长度一致"); } List<Integer> mergedList = new ArrayList<>(A.size()); for (int i = 0; i < A.size(); i++) { Integer aElement = A.get(i); // 若A的元素为null,则取B对应位置的元素,否则保留A的元素 mergedList.add(aElement != null ? aElement : B.get(i)); } return mergedList; } }
方式二:原地修改(节省内存空间)
如果允许修改原List A,可直接原地替换,无需创建新List:
public static void mergeInPlace(List<Integer> A, List<Integer> B) { if (A.size() != B.size()) { throw new IllegalArgumentException("两个List必须保持长度一致"); } for (int i = 0; i < A.size(); i++) { if (A.get(i) == null) { A.set(i, B.get(i)); } } }
2. Java 8+ Stream API实现(简洁风格)
利用Stream的IntStream.range遍历索引,结合Optional处理null,代码更简洁,性能与单循环接近:
import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.Optional; public class ListMerger { public static List<Integer> mergeWithStream(List<Integer> A, List<Integer> B) { if (A.size() != B.size()) { throw new IllegalArgumentException("两个List必须保持长度一致"); } return IntStream.range(0, A.size()) .mapToObj(i -> Optional.ofNullable(A.get(i)).orElse(B.get(i))) .collect(Collectors.toList()); } }
关键优化点
- 避免双层循环:原双层循环存在不必要的重复遍历,按索引一一对应处理只需一次遍历,时间复杂度从
O(n²)降至O(n) - 空间可控:可选择创建新List或原地修改,根据业务场景灵活调整
- 边界处理:增加长度校验,提前规避索引越界风险
内容的提问来源于stack exchange,提问作者Long Ngô Hoàng
相关产品推荐
相关产品推荐

