How can implement iteration done with multiple loops using Java 8 ?
I need to check if one of the nested objects contains the specified String
i.e. "BA"
or not?
if(errorEntities!=null) {
for(ErrorEntity errorEntity : errorEntities){
for(ErrorItemDetail errorItem : errorEntity.getErrorItem()){
List<EntityRef> relatedEntity = errorItem.getRelatedEntity();
if(relatedEntity!=null || !relatedEntity.isEmpty()){
for(EntityRef entityRef : relatedEntity){
return entityRef.getReferredType().equalsIgnoreCase("BA");
}
}
}
}
}
CodePudding user response:
Hope this is what you were looking for:
if(errorEntities!=null) {
return errorEntities.stream()
.map((ErrorEntity errorEntity) -> errorEntity.getErrorItem())
.flatMap(Collection::stream)
.map((ErrorItemDetail errorItemDetail) -> errorItemDetail.getRelatedEntity())
.filter((List<EntityRef> relatedEntity) -> relatedEntity == null || relatedEntity.isEmpty())
.flatMap(Collection::stream)
.anyMatch((EntityRef entityRef) -> entityRef.getReferredType().equalsIgnoreCase("BA"));
}
CodePudding user response:
We have 3 levels of nested lists. At the bottom of this hierarchy we have many lists of entityRefs. We are going to collects entityRefs from all of these lists into a single stream. Then we are going to see if any one of them has reference type of "BA":
return errorEntities != null && errorEntities.stream()
.flatMap(errorEntity -> errorEntity.getErrorItem().stream())
.map(errorItem -> errorItem.getRelatedEntity())
.filter(relatedEntity -> relatedEntity != null)
.flatMap(relatedEntity -> relatedEntity.stream())
.anyMatch(entityRef -> entityRef.getReferredType().equalsIgnoreCase("BA"))
We can also do it with method references. Here we are going to create a stream of all reference type Strings in upper case. Then we are going to see if any one of them is "BA"
return errorEntities != null && errorEntities.stream()
.map(ErrorEntity::getErrorItem)
.flatMap(List::stream)
.map(ErrorItemDetail::getRelatedEntity)
.filter(Objects::nonNull)
.flatMap(List::stream)
.map(EntityRef::getReferredType)
.map(String::toUpperCase)
.anyMatch("BA"::equals));
CodePudding user response:
So you have a list of ErrorEntity
and a string token ("BA"
).
And you need to find out whether you have at least one EntityRef
object deeply nested inside the ErrorEntity
that has a property that matches the token.
Judging by the code you've listed there could be null
values on different levels of your collections, which isn't a good situation from the perspective of clean-coding. But you can deal with it using static method Stream.ofNullable
available with Java 9 which returns an empty stream or a stream containing one element (argument that has been passed to it).
Make use of flatMap()
when you need to produce a stream from a single stream element and anyMatch()
to obtain a boolean
value as a result.
public static boolean matches(List<ErrorEntity> source, String token) {
return Stream.ofNullable(source) // Stream<List<ErrorEntity>>
.flatMap(List::stream) // Stream<ErrorEntity>
.flatMap(errorEntity -> errorEntity.getErrorItem().stream()) // Stream<ErrorItemDetail>
.flatMap(errorItem -> Stream.ofNullable(errorItem.relatedEntity())) // Stream<EntityRef>
.anyMatch(entityRef -> entityRef.getReferredType().equalsIgnoreCase(token));
}
If by saying Java 8 you don't mean "Java-8 streams", but that the version you are currently using is 8, then you can make use of the method Objects.nonNull()
for null-checks:
public static boolean matches(List<ErrorEntity> source, String token) {
return Stream.of(source) // Stream<List<ErrorEntity>>
.filter(Objects::isNull)
.flatMap(List::stream) // Stream<ErrorEntity>
.flatMap(errorEntity -> errorEntity.getErrorItem().stream()) // Stream<ErrorItemDetail>
.map(ErrorItemDetail::relatedEntity) // Stream<List<EntityRef>>
.filter(Objects::nonNull) // Stream<List<EntityRef>>
.flatMap(List::stream) // Stream<EntityRef>
.anyMatch(entityRef -> entityRef.getReferredType().equalsIgnoreCase(token));
}