This question is an extension to the post: Java 8 groupingby with returning multiple field.
For the same problem, how do you return a list of Customer
? For example, it should return:
Customer("A",4500,6500)
Customer("B",3000,3500)
Customer("C",4000,4500)
@Pankaj Singhal's post is the right idea if you want a Map<String, Customer>
as the result set +1. However, I would extract the merging logic into its own function e.g. in the Customer
class you would have a function as such:
public static Customer merge(Customer first, Customer second) {
first.setTotal(first.getTotal() + second.getTotal());
first.setBalance(first.getBalance() + second.getBalance());
return first;
}
Then the stream query would become:
Map<String, Customer> retObj =
listCust.stream()
.collect(Collectors.toMap(Customer::getName, Function.identity(), Customer::merge));
listCust.stream()
creates a stream object i.e. Stream<Customer>
.collect
performs a mutable reduction operation on the elements of
this stream using the provided Collector
.toMap
is the provided collector, the toMap
method extracts the keys Customer::getName
and values Function.identity()
and if the mapped keys contain duplicates, the merge function Customer::merge
is used to resolve collisions.There are three benefits I see with extracting the merging logic into its own function:
if however, your intention is to retrieve a Collection<Customer>
:
Collection<Customer> result = listCust.stream()
.collect(Collectors.toMap(Customer::getName,
Function.identity(),
Customer::merge))
.values();
or List<Customer>
as the result set then all you have to do is call values()
and pass the result of that to the ArrayList
constructor:
List<Customer> result = new ArrayList<>(listCust.stream()
.collect(Collectors.toMap(Customer::getName,
Function.identity(),
Customer::merge))
.values());
Update:
if you don't want to mutate the objects in the source then simply modify the merge
function as follows:
public static Customer merge(Customer first, Customer second) {
Customer customer = new Customer(first.getName(), first.getTotal(), first.getBalance());
customer.setTotal(customer.getTotal() + second.getTotal());
customer.setBalance(customer.getBalance() + second.getBalance());
return customer;
}
and everthing else stays as is.