group by java8

本文通过示例介绍如何使用 Java 8 的 Stream API 对集合进行分组操作,包括按价格分组并收集相关商品信息,以及进一步将商品名称转换为 Set 集合以去除重复项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.2 Group by Price – Collectors.groupingBy and Collectors.mapping example.

Java8Examples4.java

package com.mkyong.java8;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class Java8Examples4 {

    public static void main(String[] args) {

        //3 apple, 2 banana, others 1
        List<Item> items = Arrays.asList(
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 20, new BigDecimal("19.99")),
                new Item("orang", 10, new BigDecimal("29.99")),
                new Item("watermelon", 10, new BigDecimal("29.99")),
                new Item("papaya", 20, new BigDecimal("9.99")),
                new Item("apple", 10, new BigDecimal("9.99")),
                new Item("banana", 10, new BigDecimal("19.99")),
                new Item("apple", 20, new BigDecimal("9.99"))
                );

        //group by price
        Map<BigDecimal, List<Item>> groupByPriceMap =
            items.stream().collect(Collectors.groupingBy(Item::getPrice));

        System.out.println(groupByPriceMap);

        // group by price, uses 'mapping' to convert List<Item> to Set<String>
        Map<BigDecimal, Set<String>> result =
                items.stream().collect(
                        Collectors.groupingBy(Item::getPrice,
                                Collectors.mapping(Item::getName, Collectors.toSet())
                        )
                );

        System.out.println(result);

    }
}

output

{
    19.99=[
            Item{name='banana', qty=20, price=19.99}, 
            Item{name='banana', qty=10, price=19.99}
        ], 
    29.99=[
            Item{name='orang', qty=10, price=29.99}, 
            Item{name='watermelon', qty=10, price=29.99}
        ], 
    9.99=[
            Item{name='apple', qty=10, price=9.99}, 
            Item{name='papaya', qty=20, price=9.99}, 
            Item{name='apple', qty=10, price=9.99}, 
            Item{name='apple', qty=20, price=9.99}
        ]
}

//group by + mapping to Set
{
    19.99=[banana], 
    29.99=[orang, watermelon], 
    9.99=[papaya, apple]
}

GroupBy

Map<Integer, Integer> totalNoThings = somethings.stream()
    .collect(Collectors.groupingBy(Something::getParentKey,
        Collectors.summingInt(Something::getNoThings)));
Java 8 的 `Stream` API 提供了强大的聚合操作支持,虽然它不像 SQL 那样直接提供 `GROUP BY` 关键字,但我们可以通过组合使用 `Collectors.groupingBy()` 来实现类似的功能。 ### 实现原理 `Collectors.groupingBy()` 是一个收集器工厂方法,它可以将流中的元素按照某个分类条件进行分组。它的基本语法如下: ```java Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier) ``` - **T**: 流中元素的类型。 - **K**: 分组依据(key)的数据类型。 - **D**: 收集后的结果数据结构,默认是一个列表 (`List`)。 #### 基本用法示例 假设我们有一系列员工信息,并希望按部门对员工进行分组。 ```java import java.util.*; import java.util.stream.Collectors; class Employee { String name; String department; public Employee(String name, String department){ this.name = name; this.department = department; } @Override public String toString(){ return "Employee{name='" + name + "', department='" + department+ "'}"; } } public class TestGroupBy { public static void main(String[] args) { List<Employee> employees = Arrays.asList( new Employee("Alice", "HR"), new Employee("Bob", "Engineering"), new Employee("Charlie", "HR") ); // 按照部门进行分组 Map<String, List<Employee>> groupedByDept = employees.stream().collect(Collectors.groupingBy(e -> e.department)); System.out.println(groupedByDept); } } ``` 运行以上程序后将会得到类似的结果: ``` {HR=[Employee{name='Alice', department='HR'}, Employee{name='Charlie', department='HR'}], Engineering=[Employee{name='Bob', department='Engineering'}]} ``` --- ### 更高级的例子 - 多级分组与汇总 我们可以不仅仅局限于单层分组,还可以结合其他收集器来进行更复杂的操作,比如双重分组以及计数等等。 例如下面这个例子展示了如何先按部门再按性别进行二级分组并统计人数: ```java Map<String, Map<String, Long>> result = people.stream() .collect(Collectors.groupingBy( Person::getDepartment, Collectors.groupingBy( Person::getGender, Collectors.counting() ) )); ``` 这里生成的是一个嵌套映射表,外部键是部门名称,内部键代表性别类别,而值则保存相应的人口数量.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值