I want to create a DataStructure which will be similar to the cartesian product of three List.
I've also referred the existing answer by Jurgen which suggest to use flatMap. I tried in that way as well. But I've condition that filterValue
list is inside types
list. So flatMap will not work here. As filterValues
can be 0 or more
. So depending on that cartesian product (we might call it as combination) will change.
Size of measures, types & filterValues
can be different for each list.
If measure
list is empty. Then the combination will be of only types & filterValues
(and measure
will be set to null
. I've added these different scenarios in my comments of if-else
block
I've following types of list:
List<String> measures
List<Type> types
List<FilterValue> filterValues
For example the Input structure is:
{
"measures": [
"m1",
"m2",
"m3"
],
"types": [
{
"type": "type-1",
//some more fields
"filterValues": [
//no filter values present
]
},
{
"type": "type-2",
//some more fields
"filterValues": [
{
"filterValue": "t2f1"
//some more fields
},
{
"filterValue": "t2f2"
//some more fields
}
]
}
]
}
Then in above case the output data structure I'm expecting is
m1 type-1 null
m1 type-2 t2f1
m1 type-2 t2f2
m2 type-1 null
m2 type-2 t2f1
m2 type-2 t2f2
m3 type-1 null
m3 type-2 t2f1
m3 type-2 t2f2
Then the same above values I'm setting into the following classes:
class SearchArea {
String measure;
String type;
TypeCombi typeFileter;
//constructor for measure & type
//constructor for all three
//getters & setters
}
class TypeCombi {
String type;
String name; //it is mapped with filterValue
//constructor for above two fields
//getters & setters
}
The class Type
& FilterValue
is as below
class Type {
String type;
List<FilterValue> filterValues;
//some more fields
//getters and setters
}
class FilterValue {
String filterValue;
//some more fields
//getters and setters
}
I'm able to achieve the expected output using following getSearchAreas
function. But in this case I'm using multiple(two) for
loops. Can this code block cleaned up using stream/flatmap
instead of two for loops
?
Also is there any better way to handle multiple if/else block ?(I've added comment above each if/else block for it's scenario)
private List<SearchArea> getSearchAreas(List<String> measures, List<Type> types){
List<SearchArea> searchAreas = new ArrayList<>();
//measures & types both are empty
if ((measures == null || measures.isEmpty())
&& (types == null || types.isEmpty()))
return Collections.emptyList();
//one or more measure and zero types
else if (measures != null && !measures.isEmpty()
&& (types == null || types.isEmpty())) {
searchAreas = measures
.stream()
.map(measure -> new SearchArea(measure, null))
.collect(Collectors.toList());
return searchAreas;
}
//zero measures and one or more types
else if ((measures == null || measures.isEmpty())) {
for (type type : types) {
if (type.getFilterValues() == null
|| type.getFilterValues().isEmpty()) {
searchAreas.add(new SearchArea(null, type.getType()));
} else {
searchAreas.addAll(type.getFilterValues()
.stream()
.map(filterValue -> new SearchArea(null,
type.getType(),
new TypeCombi(type.getType(),
filterValue.getFilterValue())))
.collect(Collectors.toList()));
}
}
return searchAreas;
}
//one or more measures and one or more types
else {
for (String measure : measures) {
for (Type type : types) {
if (type.getFilterValues() == null
|| type.getFilterValues().isEmpty()) {
searchAreas.add(new SearchArea(measure, type.getType()));
} else {
searchAreas.addAll(type.getFilterValues()
.stream()
.map(filterValue -> new SearchArea(measure,
type.getType(),
new TypeCombi(type.getType(),
filterValue.getFilterValue())))
.collect(Collectors.toList()));
}
}
}
return searchAreas;
}
}
It will be great if someone can help me in restructuring above in cleaner fashion.