Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 stream through multiple layers and concatenate all items at the bottom-most layer

I currently have a multiple layer structure data that is like this:

Industry class has a private field Set<Company> that can be null.

Company class has a private field Set<Division> that can be null.

Division class has a private field Set<Group> that can be null.

Group class has a private field groupName that can be null and is retrievable with a getter (getGroupName()).

I am trying to stream an instance of Industry all way down to the Group layer and concatenate all the groupName's into one String with "/" in between.

If the this instance of Industry doesn't contain any groupName, return the string "null".

Based on my limited knowledge of Java 8, I am thinking of coding like this:

industry.stream()
     .flatmap(industry -> industry.getCompanies().stream())
     .filter(Objects::nonNull)
     .flatmap(company -> company.getDivisions().stream())
     .filter(Objects::nonNull)
     .flatmap(division -> division.getGroups().stream())
     .map(group -> group.getGroupName)
     .collect(Collectors.joining("/")));

This code seems to flawed in someway. Also, I am not sure where to add the statement that if Industry cannot retrieve any groupName, rather than concatenate all groupName into one string simply return a string "null".

What is the proper way to use Java 8 stream in my situation?

Thanks.

like image 574
pike Avatar asked Jan 29 '23 15:01

pike


1 Answers

Collectors.joining(…) is based on the class StringJoiner. It offers its delimiter, prefix, and suffix features, but unfortunately not the ability to provide the empty value.

To add that feature, we’ll have to re-implement Collectors.joining, which thankfully is not so hard when using StringJoiner.

Change the last line of your stream operation

.collect(Collectors.joining("/"));

to

.filter(Objects::nonNull) // elide all null elements
.collect(()->new StringJoiner("/", "", "").setEmptyValue("null"), // use "null" when empty
         StringJoiner::add, StringJoiner::merge).toString();
like image 167
Holger Avatar answered Feb 02 '23 10:02

Holger