I have an object which looks similar to what's shown below:
public class Obj {
private List<Obj> objs;
private String objId;
public List<Obj> getObjs() {
return objs;
}
public String getobjId() {
return objId;
}
@Override
public String toString() {
return "Obj [objs=" + objs + ", objId=" + objId + "]";
}
}
How can I print the list of objId
using streams?
EDIT
Obj
can contain a list of Obj and it's children can contain a list of obj objects. If the depth is 5 levels, is it possible to print all the objId values from the top most obj to the values of the child at 5th level. I want to avoid nested for loops.
You should use recursion. One possible way to do it with streams is as follows:
private Stream<Obj> allObjs() {
return Stream.concat(
Stream.of(this),
objs == null ? Stream.empty() : objs.stream().flatMap(Obj::allObjs));
}
@Override
public String toString() {
return allObjs()
.map(Obj::getobjId)
.collect(Collectors.joining(", "));
}
Note that this works well as long as your Obj
instances are arranged in a tree-like structure. If you have a specific Obj
instance that is both a parent at some level and a child in some lower level (i.e. if your Obj
instances form a graph), this solution won't work and you'll get a huge StackOverflowError
.
If you can't modify the Obj
class, you could achieve the same with helper methods that receive an instance of Obj
i.e. in a ObjService
class:
public static Stream<Obj> allObjs(Obj o) {
if (o == null) return Stream.empty(); // in case the argument is null
return Stream.concat(
Stream.of(o),
o.getObjs() == null ?
Stream.empty() :
o.getObjs().stream().flatMap(ObjService::allObjs));
}
public static String deepToString(Obj o) {
return ObjService.allObjs(o)
.map(Obj::getobjId)
.collect(Collectors.joining(", "));
}
Well, using Stream
you can start from here:
objs.stream().
map(Obj::getObjId).
forEachOrdered(System.out::println);
And improving a little bit:
List<String> collect = objs.stream()
.filter(Objects::nonNull) // Filter only nonNull objects. Avoid NullPointerException
.map(Obj::getObjId)
.peek(System.out::println) // Print the ObjId value from Obj
.collect(Collectors.toList()); // Return the result to a List, if you need.
Now you have the basic way to get values from children. Learn a little about Stream
and improve the code example ;)
Some nice links:
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With