I want to know how to extract a List<D>
from a HashMap<E,R>
considering these constraints:
E
is a custom class;R
is a custom class containing a Set<D>
of custom objects;What I have tried: I tried addressing the issue in this question.
In that previous case, I had a simple Map<E,List<R>>
, but in this case I have to access the R
class which has the targeted Set<D>
.
What I want to do in the following portion of the code is to get the Elements of the Set<D>
whose country names are equal to the given parameter.
I have tried using the same solution :
Map<E,R> map = new HashMap<E,R>();
public List<D> method(String countryname) {
return map.values().stream().filter((x)->{
return x.getSet().stream().anyMatch((t) -> {
return t.getCountry().equals(countryname);
});
})
.map(R::getSet)
.flatMap(List::stream)
.collect(Collectors.toList()); //does not compile
}
// the R class
class R {
private Set<D> set = new TreeSet<D>();
//getters & setters & other attributes
}
One way to convert is to use the constructor of the ArrayList. In order to do this, we can use the keySet() method present in the HashMap. This method returns the set containing all the keys of the hashmap.
I believe the flatMap
step is wrong, since your map
step transforms your Stream<R>
to a Stream<Set<D>>
, so flatMap(List::stream)
should be flatMap(Set::stream)
:
return map.values()
.stream()
.filter(x -> x.getSet().stream().anyMatch(t -> t.getCountry().equals(countryname)))
.map(R::getSet)
.flatMap(Set::stream)
.collect(Collectors.toList());
Besides, as you can notice above, the code can be much more readable if you avoid using curly braces when you don't have to.
In order to improve readability of your code I would suggest avoiding unnecessary curly braces in lambdas and even the lambdas themselves. Use method references where possible.
return map.values()
.stream()
.map(R::getSet)
.filter(set -> set.stream()
.map(R::getCountry)
.anyMatch(countryname::equals))
.flatMap(Set::stream)
.collect(toList());
The last flatMap
and collect
operations can be shortened to one line:
.collect(ArrayList::new, List::addAll, List::addAll);
Or if you're using Java 9:
.collect(flatMapping(Set::stream, toList()));
However it's just a matter of taste.
get the Elements of the Set whose country names are equal to the given parameter.
You seem to be looking for
// input as parameter to the method for simplicity
public List<D> method(Map<E, R> map, String countryName) {
return map.values() // Collection<R>
.stream() // Stream<R>
.flatMap(a -> a.getSet().stream()) // Stream<D>
.filter(t -> t.getCountry().equals(countryName)) // filtered
.collect(Collectors.toList()); // collected to list
}
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