How to extract a List<D> from a HashMap<E,R> using stream

空扰寡人 提交于 2021-02-07 12:27:17

问题


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
}

回答1:


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.




回答2:


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.




回答3:


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
}


来源:https://stackoverflow.com/questions/54070685/how-to-extract-a-listd-from-a-hashmape-r-using-stream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!