Reputation: 463
I have following structure.
Request {
List<Param> paramList;
Date startDate;
Date endDate;
}
Param {
String paramId;
List<DataParam> dataParams;
}
DataParam {
String dataId;
List<String> values;
}
CustomRequest {
List<NewDataParam> newDataParam;
Date startDate;
Date endDate;
}
NewDataParam {
String paramId;
String dataId;
----
}
Iterating over the request with paramList, I want to make map of paramId and generated request like Map<String, List<CustomRequest>>
.
With following code, I got Map<String, List<List<CustomRequest>>>
. Can someone suggest how to get Map<String, List<CustomRequest>>
.
request.paramList().stream()
.collect(Collectors.groupingBy(Param::getParamId,
Collectors.mapping(i -> i.dataParams().stream()
.map(r -> customBuildMethod(i.dataParamId(), r, request)).collect(Collectors.toList()), Collectors.toList())));
private CustomRequest customBuildMethod(String paramId ...) {
CustomRequest customRequest = new CustomRequest();
//mapping
return customRequest;
}
Upvotes: 3
Views: 264
Reputation: 393821
If you can use Java 9, you can achieve your goal with Collectors.flatMapping:
request.paramList()
.stream()
.collect(Collectors.groupingBy(Param::getParamId,
Collectors.flatMapping(i -> i.dataParams().stream().map(r -> customBuildMethod(i.dataParamId(), r, request))),
Collectors.toList())));
In Java 8, you can do the following:
Map<String, List<CustomRequest>> result =
request.paramList()
.stream()
.collect(Collectors.groupingBy(Param::getParamId,
Collector.of(ArrayList::new,
(l,i)->l.addAll(i.dataParams().stream().map(r -> customBuildMethod(i.dataParamId(), r, request)).collect(Collectors.toList())),
(l1,l2)->{l1.addAll(l2);return l1;})));
Upvotes: 5
Reputation: 42184
Instead of Collectors.mapping()
you can use Collectors.collectingAndThen()
where in finisher function you can do a flatMap using list of data params. Something like that:
Map<String, List<CustomRequest>> map = params.stream()
.collect(Collectors.groupingBy(
Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
.flatMap(i -> i.getDataParams().stream())
.map(r -> new CustomRequest(Arrays.asList(new NewDataParam()), new Date(), new Date()))
.collect(Collectors.toList())
))
);
System.out.println(map);
Full example I used for tests:
import java.util.*;
import java.util.stream.Collectors;
public class ListOfListsToMapOfStringAndListExample {
public static void main(String[] args) {
final List<Param> params = Arrays.asList(
new Param("1", Arrays.asList(new DataParam("2", Arrays.asList("a", "b")))),
new Param("3", Arrays.asList(new DataParam("4", Arrays.asList("c", "d")))),
new Param("5", Arrays.asList(new DataParam("6", Arrays.asList("e", "f"))))
);
Map<String, List<CustomRequest>> map = params.stream()
.collect(Collectors.groupingBy(
Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
.flatMap(i -> i.getDataParams().stream())
.map(r -> new CustomRequest(Arrays.asList(new NewDataParam()), new Date(), new Date()))
.collect(Collectors.toList())
))
);
System.out.println(map);
}
static class Request {
List<Param> paramList;
Date startDate;
Date endDate;
public Request(List<Param> paramList, Date startDate, Date endDate) {
this.paramList = paramList;
this.startDate = startDate;
this.endDate = endDate;
}
}
static class Param {
String paramId;
List<DataParam> dataParams;
public Param(String paramId, List<DataParam> dataParams) {
this.paramId = paramId;
this.dataParams = dataParams;
}
public String getParamId() {
return paramId;
}
public List<DataParam> getDataParams() {
return dataParams;
}
}
static class DataParam {
String dataId;
List<String> values;
public DataParam(String dataId, List<String> values) {
this.dataId = dataId;
this.values = values;
}
public String getDataId() {
return dataId;
}
public List<String> getValues() {
return values;
}
}
static class CustomRequest {
List<NewDataParam> newDataParam;
Date startDate;
Date endDate;
public CustomRequest(List<NewDataParam> newDataParam, Date startDate, Date endDate) {
this.newDataParam = newDataParam;
this.startDate = startDate;
this.endDate = endDate;
}
public List<NewDataParam> getNewDataParam() {
return newDataParam;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
@Override
public String toString() {
return "CustomRequest{" +
"newDataParam=" + newDataParam +
", startDate=" + startDate +
", endDate=" + endDate +
'}';
}
}
static class NewDataParam {
@Override
public String toString() {
return "NewDataParam{}";
}
}
}
Output:
{1=[CustomRequest{newDataParam=[NewDataParam{}], startDate=Wed Feb 14 09:03:21 CET 2018, endDate=Wed Feb 14 09:03:21 CET 2018}], 3=[CustomRequest{newDataParam=[NewDataParam{}], startDate=Wed Feb 14 09:03:21 CET 2018, endDate=Wed Feb 14 09:03:21 CET 2018}], 5=[CustomRequest{newDataParam=[NewDataParam{}], startDate=Wed Feb 14 09:03:21 CET 2018, endDate=Wed Feb 14 09:03:21 CET 2018}]}
In case of passing param.paramId
to customBuildMethod
you can even get rid of flatMap()
onparam.dataParams
and map your initial param object to a CustomRequest
. Something like:
Map<String, List<CustomRequest>> map = params.stream()
.collect(Collectors.groupingBy(
Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
.map(param -> customBuildMethod(param.paramId, param.dataParams))
.collect(Collectors.toList())
))
);
In this example I pass param.paramId
and param.dataParams
to this helper method which creates CustomRequest
object. It can use a list of data params to create a new list of new data params objects:
private static CustomRequest customBuildMethod(String paramId, List<DataParam> params) {
return new CustomRequest(
params.stream().map(dataParam -> new NewDataParam()).collect(Collectors.toList()),
new Date(),
new Date()
);
}
Or more directly according to your code:
Map<String, List<CustomRequest>> map = params.stream()
.collect(Collectors.groupingBy(
Param::getParamId, Collectors.collectingAndThen(Collectors.toList(), it -> it.stream()
.map(param -> customBuildMethod(param.paramId, r, request))
.collect(Collectors.toList())
))
);
Upvotes: 4