Java 8流:相同项的单位总和

Jan*_*sen 4 java-8 java-stream

是否有一种简洁的方法可以将列表中相同类型的项目的单元与Java 8流相加?例如,假设我有三个项目的列表:

{id: 10, units: 1}
{id: 20, units: 2}
{id: 10, units: 1}
Run Code Online (Sandbox Code Playgroud)

我喜欢这样的摘要流:

{id: 10, units 2}
{id: 20, units 2}
Run Code Online (Sandbox Code Playgroud)

它总结了相同id的项目单位.有任何想法吗?


这是Federico的解决方案(使用Lombok):

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


public class So44348207 {

    public static void main(String[] args) {
        List<Item> items = Arrays.asList(
            new Item(10,1), new Item(20,2), new Item(10, 1)
        );

        Map<Long, Integer> results = items.stream().collect(
            Collectors.toMap(
                Item::getId,
                Item::getUnits,
                Integer::sum
                )
            );

        results.forEach( (k,v) -> System.out.println(
            String.format("{id: %d, units: %d}", k,v))
        );
    }

    @Data
    @AllArgsContructor
    public static class Item {
        Long id;
        Integer units;
    }
}
Run Code Online (Sandbox Code Playgroud)

正确地产生:

java So44348207 
{id: 20, units: 2}
{id: 10, units: 2}
Run Code Online (Sandbox Code Playgroud)

Fed*_*ner 5

假设您有一个MyClass封装了两个字段并且具有getter 的类,您可以按如下方式执行:

Map<Long, Integer> result = list.stream()
    .collect(Collectors.toMap(
        MyClass::getId,
        MyClass::getUnits,
        Integer::sum));
Run Code Online (Sandbox Code Playgroud)

我也假设id是类型longLongunits类型intInteger.

Collectors.toMap创建一个映射,其键由其第一个参数确定,该参数是将流的元素映射到映射的键的函数.第二个参数是将流的元素映射到映射的值的函数,第三个参数是在键上存在冲突时合并两个值的运算符.