如何通过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
相关产品推荐
相关产品推荐

