Reputation: 605
I have a very simple code snippet that I would like to be converted to Java 8's list streaming methods. Any help would be really appreciated.
I have 2 collections one is a Set of String and other a list of a simple POJO which itself consists a list of string. Below is the relevant code:
POJO sample
public class SimplePojo {
private long id;
private String name;
private List<String> desiredStringList;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getDesiredStringList() {
return desiredStringList;
}
public void setDesiredStringList(List<String> desiredStringList) {
this.desiredStringList= desiredStringList;
}
}
Comparison that I am wishing to transform
Set<String> someStrings // Contains a list of strings that needs to be compared
List<SimplePojo> pojoObjectList // Contains list of SimplePojo objects
/* Each of someStrings need to be compared to each of SimplePojo.name property
and corresponding actions which is List object needs to be populated as a separate list
Below is the code snippet which has a mixture of Java 8 stream and regular For-Each loop
*/
Set<String> desiredStrings = new HashSet<String>();
for(String s : someStrings) {
List<String> interimDesiredStrings = pojoObjectList.stream()
.filter(o -> StringUtils.equals(s, o.getName()))
.flatMap(o -> o.getDesiredStringList().stream())
.collect(Collectors.toList());
desiredStrings.addAll(interimDesiredStrings);
}
Upvotes: 1
Views: 1023
Reputation: 298103
Well, this perfectly demonstrates, where overusing third-party utility functions leads to.
You are using StringUtils.equals
and there’s no sign of whether this is the Apache Commons version or the Spring version (or yet another library having such a function). Or why you are using this special method.
In the Apache case, it would be justified, if it is at least version 3 and getName()
is declared to return CharSequence
, in the Spring case, it’s not justified at all. Besides supporting CharSequence
in the Apache case, both variants merely exist to handle null
silently, but if handling null
really is your concern, using the standard Objects.equals
instead would immediately clarify the intention. Perhaps, even null
isn’t you concern.
The reason, why this is so important, is that your task can be easily implemented using standard equality semantics
Set<String> desiredStrings = pojoObjectList.stream()
.filter(o -> someStrings.contains(o.getName()))
.flatMap(o -> o.getDesiredStringList().stream())
.collect(Collectors.toSet());
Assuming that someStrings
refers to a Set
with a reasonable lookup efficiency (as with most Set
implementations), this will be significantly more efficient than your nested iterations.
Note that if the Set
referenced by someStrings
does not support null
, it would imply that a null
name is not “desired”, hence, if getName()
could return null
, changing the filter to
.filter(o -> o.getName()!=null && someStrings.contains(o.getName()))
would solve this in a clear way.
Upvotes: 2
Reputation: 28133
Why not go over the list of objects once and just check if the name is in the set of names to match?
Set<String> desiredStrings = pojoObjectList.stream()
.filter(o -> someStrings.contains(o.getName()))
.flatMap(o -> o.getDesiredStringList().stream())
.collect(toSet());
Upvotes: 1