问题
I am learning many new features of lambda and wondering how can I group by my custom object list based on certain properties as key? For example, I have list of object like this in json.
[{ "account" : "checking", "source" : "BOA" }, { "account" : "checking", "source" : "TD" }, { "account" : "saving", "source" : "WS" } ]
I am looking for way to group using java 8 feature to get output like this (grouping source as comma separated for same account.
[{ "account" : "checking", "source" : "BOA, TD" }, { "account" : "saving", "source" : "WS" } ]
Thanks
回答1:
What about this solution
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Data {
public static void main(String ab[]) {
List<Data> dataList = Arrays.asList(new Data("checking", "BOA"), new Data("checking", "TD")
, new Data("saving", "WS"));
List<Data> newList = new ArrayList<>(dataList.stream()
.collect(Collectors.toMap(Data::getAccount, d -> d, (d1, d2) -> new Data(d1.account, d1.source + ", " + d2.source)))
.values());
System.out.println("dataList = " + dataList);
System.out.println("newList = " + newList);
}
private String account;
private String source;
Data(String account, String source) {
this.account = account;
this.source = source;
}
@Override
public String toString() {//just override toString as json object with out using jon passer
return "{ \"account\" : \""+account+"\", \"source\" : \""+source+"\" }";
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
}
回答2:
You can use the java stream groupingBy
Map<String, String> resultMap= records.stream().
collect(groupingBy(Record::getAccount, mapping(Record::getSource, joining(","))));
public class Record {
String account;
String source;
// constructors
...
// getters
public String getAccount (){
return account;
}
public String getSource (){
return source;
}
//setters
....
}
回答3:
Considering the object itself is named Dto
having private fields account
and source
being instantiated with a constructor with both fields and they are available through getters, then you can use Collectors.toMap
reducing values wrapped in Collectors.collectingAndThen
extracting only the values from the newly created Map
:
List<Dto> reducedList = list.stream().collect(
Collectors.collectingAndThen(
Collectors.toMap(
Dto::getAccount,
dto -> new Dto(dto.getAccount(), dto.getSource()),
(d1, d2) -> new Dto(d1.getAccount(), String.join(", ", d1.getSource(), d2.getSource()))
),
map -> new ArrayList<>(map.values())));
This solution is suspiciously similar to my answer for this question: Collectors.reducing to List. However, this question came earlier by 6 hours.
来源:https://stackoverflow.com/questions/61924108/grouping-the-custom-object-list-by-properties-using-java-8