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

如何从两个含Position对象的ArrayList中提取完全匹配的账户?

筛选符合条件的账户:Java实现方案

前提准备

要判断两个Position对象是否完全匹配,必须重写该类的equals()和hashCode()方法,基于所有属性的值进行比较(默认的对象比较是引用地址比较,无法满足需求):

import java.util.Objects;

public class Position {
    private String account;
    private String date;
    private String cycle;
    private String status;

    // 构造器
    public Position(String account, String date, String cycle, String status) {
        this.account = account;
        this.date = date;
        this.cycle = cycle;
        this.status = status;
    }

    // Getter方法
    public String getAccount() { return account; }
    public String getDate() { return date; }
    public String getCycle() { return cycle; }
    public String getStatus() { return status; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Position position = (Position) o;
        return Objects.equals(account, position.account) &&
               Objects.equals(date, position.date) &&
               Objects.equals(cycle, position.cycle) &&
               Objects.equals(status, position.status);
    }

    @Override
    public int hashCode() {
        return Objects.hash(account, date, cycle, status);
    }
}

方案一:Java Stream实现(高效简洁)

通过分组+过滤的方式实现,核心思路是:

  1. 将两个列表按account分组,得到账户到对应Position集合的映射
  2. 遍历ListA的分组,检查每个账户是否满足:ListB中存在该账户的分组、两组元素数量一致、ListA的所有Position都在ListB的分组中存在

为了提升匹配效率,可将ListB的分组转为Set(contains操作时间复杂度从O(n)降为O(1)):

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

public class PositionProcessor {
    public static void main(String[] args) {
        // 初始化示例数据
        List<Position> listA = Arrays.asList(
                new Position("ACC1", "20-Jan-23", "1", "open"),
                new Position("ACC1", "20-Jan-23", "2", "closing"),
                new Position("ACC2", "20-Jan-23", "1", "open"),
                new Position("ACC2", "20-Jan-23", "2", "closing"),
                new Position("ACC3", "20-Jan-23", "1", "open"),
                new Position("ACC3", "20-Jan-23", "2", "closing")
        );

        List<Position> listB = Arrays.asList(
                new Position("ACC1", "20-Jan-23", "1", "open"),
                new Position("ACC1", "20-Jan-23", "2", "closing"),
                new Position("ACC2", "20-Jan-23", "1", "open"),
                new Position("ACC2", "20-Jan-23", "2", "closed"),
                new Position("ACC3", "20-Jan-23", "1", "open")
        );

        // 按account分组,ListB转为Set提升匹配效率
        Map<String, List<Position>> groupA = listA.stream()
                .collect(Collectors.groupingBy(Position::getAccount));
        Map<String, Set<Position>> groupB = listB.stream()
                .collect(Collectors.groupingBy(Position::getAccount, Collectors.toSet()));

        // 筛选符合条件的账户
        Set<String> validAccounts = groupA.entrySet().stream()
                .filter(entry -> {
                    String account = entry.getKey();
                    List<Position> posA = entry.getValue();
                    Set<Position> posB = groupB.get(account);

                    return posB != null 
                            && posA.size() == posB.size() 
                            && posB.containsAll(posA);
                })
                .map(Map.Entry::getKey)
                .collect(Collectors.toSet());

        System.out.println("符合条件的账户:" + validAccounts); // 输出 [ACC1]
    }
}

方案二:标准循环实现(无Stream依赖)

如果项目不支持Java 8+的Stream特性,可以用传统循环分组+匹配:

import java.util.*;

public class PositionProcessor {
    public static void main(String[] args) {
        // 初始化示例数据(同方案一)
        List<Position> listA = Arrays.asList(
                new Position("ACC1", "20-Jan-23", "1", "open"),
                new Position("ACC1", "20-Jan-23", "2", "closing"),
                new Position("ACC2", "20-Jan-23", "1", "open"),
                new Position("ACC2", "20-Jan-23", "2", "closing"),
                new Position("ACC3", "20-Jan-23", "1", "open"),
                new Position("ACC3", "20-Jan-23", "2", "closing")
        );

        List<Position> listB = Arrays.asList(
                new Position("ACC1", "20-Jan-23", "1", "open"),
                new Position("ACC1", "20-Jan-23", "2", "closing"),
                new Position("ACC2", "20-Jan-23", "1", "open"),
                new Position("ACC2", "20-Jan-23", "2", "closed"),
                new Position("ACC3", "20-Jan-23", "1", "open")
        );

        // 手动分组ListA
        Map<String, List<Position>> groupA = new HashMap<>();
        for (Position p : listA) {
            groupA.computeIfAbsent(p.getAccount(), k -> new ArrayList<>()).add(p);
        }

        // 手动分组ListB并转为Set
        Map<String, Set<Position>> groupB = new HashMap<>();
        for (Position p : listB) {
            groupB.computeIfAbsent(p.getAccount(), k -> new HashSet<>()).add(p);
        }

        // 筛选符合条件的账户
        Set<String> validAccounts = new HashSet<>();
        for (Map.Entry<String, List<Position>> entry : groupA.entrySet()) {
            String account = entry.getKey();
            List<Position> posA = entry.getValue();
            Set<Position> posB = groupB.get(account);

            if (posB == null || posA.size() != posB.size()) {
                continue;
            }

            boolean allMatch = true;
            for (Position p : posA) {
                if (!posB.contains(p)) {
                    allMatch = false;
                    break;
                }
            }

            if (allMatch) {
                validAccounts.add(account);
            }
        }

        System.out.println("符合条件的账户:" + validAccounts); // 输出 [ACC1]
    }
}

效率说明

两种方案的时间复杂度均为O(n + m)(n、m分别为ListA和ListB的元素数量),分组操作是线性遍历,匹配操作基于Set的O(1)查询,整体属于高效实现,适合处理大规模数据。

内容的提问来源于stack exchange,提问作者Enthu Leo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 21:30:55