流的多层次分组

1.简介

使用Java 8流,可以很容易地根据不同的标准对对象集合进行分组。 在这篇文章中,我们将看到如何从简单的单级分组到更复杂的,涉及多个级分组的分组。

我们将使用两个类来表示我们要分组的对象:人和宠物。

人类

public class Person {
    private final String name;
    private final String country;
    private final String city;
    private final Pet pet;
    
    public Person(String name, String country, String city, Pet pet) {
        this.name = name;
        this.country = country;
        this.city = city;
        this.pet = pet;
    }
    
    public String getName() {
        return name;
    }
    
    public String getCountry() {
        return country;
    }
    
    public String getCity() {
        return city;
    }
    
    public Pet getPet() {
        return pet;
    }
    
    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", country='" + country + '\'' +
            ", city='" + city + '\'' +
            '}';
    }
}

宠物课

public class Pet {
    private final String name;
    private final int age;
    
    public Pet(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    @Override
    public String toString() {
        return "Pet{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

在主要方法中,我们创建将在以下各节中使用的集合。

public static void main(String[] args) {
    Person person1 = new Person("John", "USA", "NYC", new Pet("Max", 5));
    Person person2 = new Person("Steve", "UK", "London", new Pet("Lucy", 8));
    Person person3 = new Person("Anna", "USA", "NYC", new Pet("Buddy", 12));
    Person person4 = new Person("Mike", "USA", "Chicago", new Pet("Duke", 10));
    
    List<Person> persons = Arrays.asList(person1, person2, person3, person4);
  • 您可以在此处查看源代码。

2.单层分组

最简单的分组形式是单级分组。 在此示例中,我们将按其国家/地区对集合中的所有人员进行分组:

public void singleLevelGrouping(List<Person> persons) {
    final Map<String, List<Person>> personsByCountry = persons.stream().collect(groupingBy(Person::getCountry));
    
    System.out.println("Persons in USA: " + personsByCountry.get("USA"));
}

如果我们查看地图,就会看到每个国家如何包含其公民列表:

单组

结果显示居住在指定国家/地区的人:

Persons in USA: [Person{name='John', country='USA', city='New York'}, Person{name='Anna', country='USA', city='New York'}, Person{name='Mike', country='USA', city='Chicago'}]

3.两级分组

在此示例中,我们将不仅按国家/地区分组,还按城市分组。 为此,我们需要实现两级分组。 我们将按国家对人员进行分组,对于每个国家,我们将按其居住城市对人员进行分组。

为了允许多级分组,类Collectors中的groupingBy方法支持附加的Collector作为第二个参数:

public static <T, K, A, D>
    Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                          Collector<? super T, A, D> downstream)

让我们使用此方法来实现我们的两级分组:

public void twoLevelGrouping(List<Person> persons) {
     final Map<String, Map<String, List<Person>>> personsByCountryAndCity = persons.stream().collect(
         groupingBy(Person::getCountry,
            groupingBy(Person::getCity)
        )
    );
    System.out.println("Persons living in London: " + personsByCountryAndCity.get("UK").get("London").size());
}

如果我们调试执行,我们将看到人员的分布情况:

twoLevelGrouping

4.三级分组

在最后一个示例中,我们将更进一步,并按国家/地区,城市和宠物的名字对人进行分组。 为了便于阅读,我将其分为两种方法:

public void threeLevelGrouping(List<Person> persons) {
    final Map<String, Map<String, Map<String, List<Person>>>> personsByCountryCityAndPetName = persons.stream().collect(
            groupingBy(Person::getCountry,
                groupByCityAndPetName()
            )
    );
    System.out.println("Persons whose pet is named 'Max' and live in NY: " +
        personsByCountryCityAndPetName.get("USA").get("NYC").get("Max").size());
}

private Collector<Person, ?, Map<String, Map<String, List<Person>>>> groupByCityAndPetName() {
    return groupingBy(Person::getCity, groupingBy(p -> p.getPet().getName()));
}

现在我们有了三个嵌套的地图,其中包含每个人员列表:

threeLevel分组

5.结论

Java 8 Collectors API为我们提供了一种对集合进行分组的简便方法。 通过嵌套收集器,我们可以添加不同的组层以实现多级分组。

翻译自: https://www.javacodegeeks.com/2016/03/multi-level-grouping-streams.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值