7

I'm still a beginner of Java 8. I'm getting stuck on filtering a Map of List values. Here is my code

public class MapFilterList {
    private static Map<String, List<Person>> personMap = new HashMap<>();

    public static void main(String[] args) {
        Person p1 = new Person("John", 22);
        Person p2 = new Person("Smith", 45);
        Person p3 = new Person("Sarah", 27);

        List<Person> group1 = new ArrayList<>();
        group1.add(p1);
        group1.add(p2);

        List<Person> group2 = new ArrayList<>();
        group2.add(p2);
        group2.add(p3);

        List<Person> group3 = new ArrayList<>();
        group3.add(p3);
        group3.add(p1);

        personMap.put("group1", group1);
        personMap.put("group2", group2);
        personMap.put("group3", group3);

        doFilter("group1").forEach(person -> {
            System.out.println(person.getName() + " -- " + person.getAge());
        });

    }

    public static List<Person> doFilter(String groupName) {
        return personMap.entrySet().stream().filter(key -> key.equals(groupName)).map(map -> map.getValue()).collect(Collectors.toList());
    }
}

How can I make to correct doFilter method because the error show me cannot convert from List<List<Person>> to List<Person>.

7
  • 1
    What you want to achieve? Why not just personMap.get(groupName)? As I understand, doFilter should do exactly this job. Commented Feb 20, 2017 at 5:57
  • @Zefick I was praticing Java8 lambda expression and Stream API. This program is just an example. I'd like to filter a map of list values via it's stream. Commented Feb 20, 2017 at 5:59
  • What do you mean by "correct the doFilter method"? Is something not working? Is there an error? What do you expect to happen? Commented Feb 20, 2017 at 6:04
  • 1
    Even when you are practicing Java 8, you should try to solve tasks that exhibit a benefit of the Stream API over the older APIs, instead of tasks that are simpler without Streams. The entire operation can be expressed as either personMap.get(groupName) or, if collecting into a new list really is required, still as simple as new ArrayList<>(personMap.get(groupName)) Commented Feb 20, 2017 at 10:29
  • 2
    But possible solutions depend on the actual problem. Even if you weren’t looking for an exact match of the key (which is what get is for), using a predicate that is known to have exactly one match implies that you could use findFirst or similar to get the particular List. Collecting into a new list is only necessary, if you know that you will have to merge multiple lists into one. Commented Feb 20, 2017 at 12:02

1 Answer 1

12

If I understood correctly you need the following code:

public static List<Person> doFilter(String groupName) {
    return personMap.entrySet().stream()
            .filter(entry -> entry.getKey().equals(groupName))
            .map(entry -> entry.getValue())
            .flatMap(List::stream)
            // as an option to replace the previous two
            // .flatMap(entry -> entry.getValue().stream()) 
            .collect(Collectors.toList());
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. This fixed my error. can you explain me why you use flatMap method ?
flatMap converts Stream<List<Person>> to Stream<Person>
You can fuse .map(entry -> entry.getValue()) .flatMap(List::stream) to a single .flatMap(entry -> entry.getValue().stream())
@Holger Thank you for more shorter way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.