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

如何通过Java Stream单次迭代统计嵌套列表的总大小

如何通过Java Stream单次迭代统计嵌套列表的总大小

当然可以做到!而且完全能通过单次Stream迭代就搞定,不用多次遍历Person列表。下面我给你一步步拆解实现方式,还会提供两种不同风格的代码供你选择:

首先,得先确保你的实体类有对应的getter方法,因为Stream需要访问Person里的地址和邮件列表。这里先补全基础的实体类定义(方便你直接测试):

class Address {
    // 根据你的实际需求补充属性,示例中用字符串初始化,这里可以加对应的构造器
    public Address(String id) {}
}

class Email {
    public Email(String email) {}
}

class Person {
    private String name;
    private int age;
    private List<Address> addresses;
    private List<Email> emails;

    public Person(String name, int age, List<Address> addresses, List<Email> emails) {
        this.name = name;
        this.age = age;
        this.addresses = addresses;
        this.emails = emails;
    }

    // Stream必须的getter方法
    public List<Address> getAddresses() {
        return addresses;
    }

    public List<Email> getEmails() {
        return emails;
    }
}

方式一:用int数组作为累加容器(简洁直接)

这种方式不需要额外定义类,用一个长度为2的int数组来分别存储地址总数和邮件总数,非常适合简单的双值统计场景:

public static void main(String[] args) {
    // 初始化你提供的测试数据
    List<Address> address1 = List.of(new Address("1"), new Address("2"), new Address("5"), new Address("6"));
    List<Address> address2 = List.of(new Address("3"), new Address("4"));
    List<Email> email1 = List.of(new Email("1@abc.com"), new Email("2@abc.com"), new Email("3@abc.com"));
    List<Email> email2 = List.of(new Email("3@xyz.com"), new Email("4@xyz.com"));
    Person person1 = new Person("smith",22, address1, email1);
    Person person2 = new Person("Alex",30, address2, email2);
    List<Person> persons = List.of(person1, person2);

    // 核心的Stream归约操作,单次迭代完成统计
    int[] totals = persons.stream()
        .reduce(
            new int[]{0, 0}, // 初始值:地址总数0,邮件总数0
            (acc, person) -> {
                acc[0] += person.getAddresses().size(); // 累加当前Person的地址数量
                acc[1] += person.getEmails().size();    // 累加当前Person的邮件数量
                return acc;
            },
            (acc1, acc2) -> { // 并行流场景下的合并逻辑,串行流也可以保留保证兼容性
                acc1[0] += acc2[0];
                acc1[1] += acc2[1];
                return acc1;
            }
        );

    int totalAddresses = totals[0]; // 结果:6
    int totalEmails = totals[1];    // 结果:5

    System.out.println("总地址数:" + totalAddresses);
    System.out.println("总邮件数:" + totalEmails);
}

方式二:自定义统计类(面向对象,可读性更强)

如果你的统计需求后续可能扩展,或者希望代码更具可读性,可以自定义一个统计结果类,用它来封装地址和邮件的统计值:

// 自定义统计类
class Stats {
    private int addressCount;
    private int emailCount;

    public Stats(int addressCount, int emailCount) {
        this.addressCount = addressCount;
        this.emailCount = emailCount;
    }

    // 提供累加方法,用于合并两个Stats对象
    public Stats merge(Stats other) {
        this.addressCount += other.addressCount;
        this.emailCount += other.emailCount;
        return this;
    }

    // 静态方法:从Person生成对应的Stats对象
    public static Stats fromPerson(Person person) {
        return new Stats(person.getAddresses().size(), person.getEmails().size());
    }

    // getter方法
    public int getAddressCount() {
        return addressCount;
    }

    public int getEmailCount() {
        return emailCount;
    }
}

// 测试代码
public static void main(String[] args) {
    // 同样初始化测试数据(和方式一一致)
    List<Address> address1 = List.of(new Address("1"), new Address("2"), new Address("5"), new Address("6"));
    List<Address> address2 = List.of(new Address("3"), new Address("4"));
    List<Email> email1 = List.of(new Email("1@abc.com"), new Email("2@abc.com"), new Email("3@abc.com"));
    List<Email> email2 = List.of(new Email("3@xyz.com"), new Email("4@xyz.com"));
    Person person1 = new Person("smith",22, address1, email1);
    Person person2 = new Person("Alex",30, address2, email2);
    List<Person> persons = List.of(person1, person2);

    // Stream处理逻辑:先转成Stats,再合并所有Stats
    Stats totalStats = persons.stream()
        .map(Stats::fromPerson)
        .reduce(new Stats(0, 0), Stats::merge);

    System.out.println("总地址数:" + totalStats.getAddressCount()); // 6
    System.out.println("总邮件数:" + totalStats.getEmailCount());   // 5
}

这两种方式都是单次遍历Person列表,在遍历每个Person的时候同时统计地址和邮件的数量,完全符合你的需求,不会出现多次迭代的情况。你可以根据自己的代码风格和实际需求选择合适的方式~

备注:内容来源于stack exchange,提问作者rev gan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 08:53:05