Below is my working code set of nested forEach
. Looking for the best alternate to make code clean. Looks to be a very complex set of code
This Model1
is a List
containing various SubList
and other few elements
List<Model1> listModel1 = getDataForModel1(......);
listModel1.getSubList1().forEach(dataSubList1 -> {
dataSubList1.getChildSublList2().forEach(dataChildSubList2 -> {
dataChildSubList2.getChildSubList3().forEach(dataChildSubList3 -> {
if (dataChildSubList3.getIsValid()) {
// Setting my required data in this dataChildSubList3 all properties
}
})
})
})
The above code is working as expected but Looking for an alternate to forEach
. Thus making the above code less complex. Thanks in advance
CodePudding user response:
It's hard to tell by your original question if you need the lists on the top layer. If all you need is the list of dataChildSubList3 you could do this:
List<Model1> listModel1 = getDataForModel1(......);
listModel1.getSubList1()
.stream()
.flatMap(dataSubList1 -> dataSubList1.getChildSublList2().stream())
.flatMap(dataSubList2 -> dataSubList2.getChildSublList3().stream())
.filter(dataSubList3::getIsValid)
.forEach(dataChildSubList3 -> {
// Setting my required data in this dataChildSubList3 all
})
CodePudding user response:
This answer should be seen as a sketch. Since the code does not explicitly define the return types, the code might not work 1:1.
In the following, I assume that:
listModel1.getSubList1()
returns aList<Data1>
,dataSubList1.getChildSublList2()
returns aList<Data2>
, anddataSubList2.getChildSublList3()
returns aList<Data3>
.
If we use Java 8 , we can utilize the stream
API:
List<Model1> listModel1 = getDataForModel1(......);
listModel1.getSubList1().stream()
// 1st block replaces 1st foreach:
.filter(Objects::nonNull) // remove nulls, just to be safe
.map(Data1::getChildSublList2) // transform each Data1-object to its list of Data2-objects
.flatMap(List::stream) // flatten: transform each list in a stream of its elements
// 2nd block replaces 2nd foreach:
.filter(Objects::nonNull) // remove nulls, just to be safe
.map(Data2::getChildSublList3) // transform each Data2-object to its list of Data3-objects
.flatMap(List::stream) // flatten: transform each list in a stream of its elements
// 3rd block replaces 3rd foreach:
.filter(Objects::nonNull) // remove nulls, just to be safe
.filter(Data3::getIsValid) // move if-condition to here
.forEach(dataChildSubList3 -> {
// Setting my required data in this dataChildSubList3 all properties
});
It would be even better if we move the lambda-body of the forEach
-lambda in a separate method (e.g. named foo
) that takes a Data3
as parameter and does the processing, this would simplify the forEach(...)
to:
listModel1.getSubList1().stream()
...
.forEach(this::foo);