You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java中对比两个Payment类型List并找差异,排查现有代码运行问题

现有代码存在的问题
  • 空指针风险:没有对rbsList、partnerList做非空校验,列表为null时遍历会直接抛出空指针异常;如果Payment的account字段为null,调用equals方法时也会触发空指针。
  • 时间复杂度过高:两层嵌套循环的时间复杂度为O(n*m),当两个列表的元素量级较大(比如超过1万条)时,运行效率极低,甚至会触发你捕获的OutOfMemoryError或者超时问题。
  • 匹配逻辑漏洞:如果同一个account+sum的组合在其中一个列表中出现多次,例如rbsList有2条相同组合的记录,partnerList只有1条,现有代码会把rbsList的两条都标记为匹配,不符合一对一匹配的业务逻辑。
  • 业务侵入性强:需要在Payment类中额外新增exist字段,修改了核心业务类的结构,适用场景受限。
  • 异常处理不合理:捕获异常后仅打印堆栈,后续的流处理逻辑仍会执行,最终得到的不匹配列表结果是错误的。
正确实现方案

推荐使用哈希表优化的实现,无需修改Payment类结构,时间复杂度降低到O(n+m),性能提升明显:

import java.util.*;
import java.util.stream.Collectors;
import java.util.AbstractMap.SimpleEntry;

private List<Payment> rbsList;
private List<Payment> partnerList;
private List<Payment> notMatchedRBS;
private List<Payment> notMatchedPartner;

public void compare() {
    // 非空校验
    if (rbsList == null) rbsList = Collections.emptyList();
    if (partnerList == null) partnerList = Collections.emptyList();
    
    // 构造partner侧的匹配键计数Map,键为<account, sum>,值为对应记录的队列
    Map<SimpleEntry<String, Integer>, Queue<Payment>> partnerMap = new HashMap<>();
    for (Payment p : partnerList) {
        String account = p.getAccount() == null ? "" : p.getAccount();
        Integer sum = p.getSum();
        SimpleEntry<String, Integer> key = new SimpleEntry<>(account, sum);
        partnerMap.computeIfAbsent(key, k -> new LinkedList<>()).offer(p);
    }
    
    Set<Payment> matchedPartner = new HashSet<>();
    notMatchedRBS = new ArrayList<>();
    
    // 遍历rbs列表匹配
    for (Payment rbs : rbsList) {
        String account = rbs.getAccount() == null ? "" : rbs.getAccount();
        Integer sum = rbs.getSum();
        SimpleEntry<String, Integer> key = new SimpleEntry<>(account, sum);
        if (partnerMap.containsKey(key) && !partnerMap.get(key).isEmpty()) {
            // 取出一个匹配的partner标记为已匹配
            matchedPartner.add(partnerMap.get(key).poll());
        } else {
            notMatchedRBS.add(rbs);
        }
    }
    
    // 收集partner侧未匹配的记录
    notMatchedPartner = partnerList.stream()
            .filter(p -> !matchedPartner.contains(p))
            .collect(Collectors.toList());
}

如果一定要保留原有exist字段的实现,可以在原有逻辑基础上补充空校验、优化匹配逻辑即可,但依然不推荐在数据量大的场景下使用。

内容的提问来源于stack exchange,提问作者my pochta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 13:06:07