java8 stream 如何按多字段分组,并对一个字段求和

新手上路,请多包涵

在mysql中通常有以下形式的分组求和需求

select a, b, c, sum(d) from t 
group by a

按sql标准来说,b,c列没有使用聚合函数,在oracle中会报错,而在mysql非严格的group by模式下,b,c的值是随机的,现在我也有一组java对象想实现类似的功能,该如何做

List<User> users;
User u1 = new User("tom", "bb", "cc", 100)
User u2 = new User("tom", "bb", "cc", 50)
User u3 = new User("jerry", "dd", "ee", 30)
User u2 = new User("jerry", "dd", "ee",40)

最后我想通过stream流实现以下效果的分组求和

User("tom", "bb", "cc", 150)
User("jerry", "dd", "ee", 70)

请教如何用stream实现### 问题描述

问题出现的环境背景及自己尝试过哪些方法

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 26.9k
1 个回答
第一次回答,希望能帮到你

User类:

class User {
    String name;
    String phone;
    String address;
    Long scope;

    public User(String name, String phone, String address) {
        this.name = name;
        this.phone = phone;
        this.address = address;
    }

    public User(String name, String phone, String address, Long scope) {
        this.name = name;
        this.phone = phone;
        this.address = address;
        this.scope = scope;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", phone='" + phone + '\'' +
                ", address='" + address + '\'' +
                ", scope=" + scope +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(name, user.name) &&
                Objects.equals(phone, user.phone) &&
                Objects.equals(address, user.address) &&
                Objects.equals(scope, user.scope);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, phone, address);
    }
}

重写equals和hashCode是为了分组。
重写toString是为了打印User的具体属性值

主体函数

public class MyTest {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<User>();
        users.add(new User("tom", "bb", "cc", 100l));
        users.add(new User("tom", "bb", "cc", 50l));
        users.add(new User("jerry", "dd", "ee", 30l));
        users.add(new User("jerry", "dd", "ee",40l));

        users.stream()
                .collect(Collectors
                        .groupingBy(
                                user -> new User(user.name, user.phone, user.address), 
                                Collectors.summarizingLong(user -> user.scope)
                        )
                )
                .forEach((k,v) -> {
                    k.scope = v.getSum();
                    System.out.println(k);
                });
    }
}

运行结果

User{name='jerry', phone='dd', address='ee', scope=70}
User{name='tom', phone='bb', address='cc', scope=150}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题