5

Would someone help me with getting the array of the map values with stream and filtering?

public class TheMap extends HashMap<String, String> {
    public TheMap(String name, String title) {
        super.put("name", name);
        super.put("title", title);
    }

    public static void main(final String[] args) {
        Map<Long, Map<String, String>>map = new HashMap<>();            

        map.put(0L, null);
        map.put(1L, new TheMap("jane", "engineer"));
        map.put(2L, new TheMap("john", "engineer"));
        map.put(3L, new TheMap(null, "manager"));
        map.put(4L, new TheMap("who", null));
        map.put(5L, new TheMap(null, null));
    }
}

The result that I am looking for is an ArrayList<TheMap> with only these two entries:

TheMap("jane", "engineer")
TheMap("john", "engineer")

Basically, retrieve TheMap with none-null name and title.

1
  • 3
    This is weird, you're putting an overridden Map into another map? Are you sure you want to do this? Don't you want a bean with just name and title properties? Commented Apr 4, 2017 at 20:23

2 Answers 2

4
List<Map<String, String>> list = 
        map.values().stream().filter(v -> 
                              v != null && 
                              !v.entrySet().isEmpty() &&
                              !v.containsValue(null)).
        collect(Collectors.toList());
Sign up to request clarification or add additional context in comments.

4 Comments

what’s the point of v.entrySet().isEmpty()? That doesn’t produce different results than v.isEmpty(). Besides that, empty maps are not within the OP’s problem description anyway.
both produce the same result. my original problem statement did not include the empty Map, but it is good to have. this way, when I add a constructor TheMap() {}, the logic would still work.
Can I post a follow-up question here. I have code to search the List<TheMap> based on Map<String, String>. Just like to know if my code is good. Map<String, String> srch = new HashMap<>(); srch.put("name", "jane"); List<Map<String, String>>fnd = list.stream().filter(e -> { boolean f = true; for (Entry<String, String>s: srch.entrySet()) f &= (e.get(s.getKey()) == s.getValue()); return f;}).collect(Collectors.toList());
Please, post a new question or update this one. As a comment, it's difficult to read your new question
3

If you need an arrayList of TheMap, try the following way:

ArrayList<TheMap> as = map.values()
   .stream()
   .filter(v -> v != null && v.get("name") != null && v.get("title") != null)
   .map(m -> (TheMap)m)
   .collect(Collectors.toCollection(ArrayList::new)));

5 Comments

there are not guarantees that the returned List is actually an ArrayList, so your cast might break in a future release. Collectors.toCollection is what you want in this case
@Holger. Sorry, I should have paid more attention on the filter to see that it was only filtering out the null values but not the key / values inside the values. See my edit.
@Eugene, as per the source code of Collectors.toList, it does in fact instantiate and return an ArrayList. Am I missing anything?
@VHS you are not missing anything, but that is exactly what makes this an implementation detail that might change. Look at the javadoc of toList and the guarantees that it does not make.
@Eugene, thanks for a nice suggestion. I edited my answer to use toCollection instead.

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.