相关文章推荐
乐观的哑铃  ·  httpClient中post请求并传送fo ...·  13 小时前    · 
有胆有识的斑马  ·  REST Clients :: ...·  13 小时前    · 
年轻有为的滑板  ·  java ...·  6 小时前    · 
俊逸的匕首  ·  java 消息模板替换 - CSDN文库·  6 小时前    · 
傻傻的香烟  ·  File.Copy 方法 ...·  4 月前    · 
乐观的机器猫  ·  Proxy error: Could ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

In Java 8 group by how to groupby on a single field which returns more than one field. In the below code by I am passing name and the field to be summed which is 'total' in this scenario. however I would like to return sum of 'total' and 'balance' field for every 'name' in the Customer list (can be a map with key and value as array). Can it be done by using a single groupingBy with the return values?

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class Sample {
    public static void main(String str[]){
        Customer custa = new Customer("A",1000,1500);
        Customer custa1 = new Customer("A",2000,2500);
        Customer custb = new Customer("B",3000,3500);
        Customer custc = new Customer("C",4000,4500);
        Customer custa2 = new Customer("A",1500,2500);
        List<Customer> listCust = new ArrayList<>();
        listCust.add(custa);
        listCust.add(custa1);
        listCust.add(custb);
        listCust.add(custc);
        listCust.add(custa2);
        Map<String, Double> retObj = 
            listCust.stream().collect(Collectors.groupingBy(Customer::getName,Collectors.summingDouble(Customer::getTotal)));
    System.out.println(retObj);
    private static class Customer {
        private String name;
        private double total;
        private double balance;
        public Customer(String name, double total, double balance) {
            super();
            this.name = name;
            this.total = total;
            this.balance = balance;
        public String getName() {
            return name;
        public void setName(String name) {
            this.name = name;
        public double getTotal() {
            return total;
        public void setTotal(double total) {
            this.total = total;
        public double getBalance() {
            return balance;
        public void setBalance(double balance) {
            this.balance = balance;
        @Override
        public String toString() {
            return "Customer [name=" + name + ", total=" + total + ", balance=" + balance + "]";

Expected Output -

A = [4500,6500], B = [3000,3500] , C = [4000,4500]

You can write your own collector to sum total and balance

Collector<Customer, List<Double>, List<Double>> collector = Collector.of(
        () -> Arrays.asList(0.0, 0.0),
        (a, t) -> {
            a.set(0, a.get(0) + t.getTotal());
            a.set(1, a.get(1) + t.getBalance());
        (a, b) -> {
            a.set(0, a.get(0) + b.get(0));
            a.set(1, a.get(1) + b.get(1));
            return a;
Map<String, List<Double>> retObj = listCust
        .stream()
        .collect(Collectors.groupingBy(Customer::getName, collector));
System.out.println(retObj);

result

{A=[4500.0, 6500.0], B=[3000.0, 3500.0], C=[4000.0, 4500.0]}

You can also use the toMap collector to accomplish the task at hand.

Map<String, List<Double>> retObj =
        listCust.stream()
                .collect(Collectors.toMap(Customer::getName,
                c -> new ArrayList<>(Arrays.asList(c.getTotal(), c.getBalance())),
                (l, l1) -> {
                    l.set(0, l.get(0) + l1.get(0));
                    l.set(1, l.get(1) + l1.get(1));
                    return l;
                You don't need to wrap the Arrays.asList(...) in a new ArrayList<>(...) since Arrays.asList is a fixed-size list that supports replacing of its values
– fps
                Feb 11, 2018 at 13:54
                @FedericoPeraltaSchaffner true, but the main purpose I passed it into the ArrayList constructor is for whatever reason the OP wants to modify the list in terms or removing, adding etc...
– Ousmane D.
                Feb 11, 2018 at 14:02
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.