2

Let's say I have a map to a map of Integers and I want filter for a key to the second map and combine the arrays for the giving key.

so basically I want to go from

Map<String, Map<String, List<Integer>>>

to

List<Integer>

For example

KeyA -> keya -> [1,2,3]
KeyB -> keya -> [4,5,6]
KeyC -> keyb -> [7,8]

The result should be if the filter value is keya [1,2,3,4,5,6], I don't really care about the first set of keys.

I don't have any issues completing this operation in a standard way of iterating.

I would like to use Streams though.

2
  • 2
    Is it Map<String, Map<Integer, List<Integer>>> or Map<String, Map<String, List<Integer>>>? Rewrite example Commented Oct 9, 2021 at 19:12
  • I edited the question solution from Dmitrii worked just fine. Commented Oct 9, 2021 at 19:16

3 Answers 3

2

There is some mistake in your description, you can't have two same keys named "keya" in the Map. But, common solution by Stream API will looks like that:

    List<Integer> collect = source.values().stream()
            .flatMap(s -> s.entrySet().stream())
            .filter(s1 -> s1.getKey().equals(1) || s1.getKey().equals(2)) //needed key here
            .map(Map.Entry::getValue)
            .flatMap(Collection::stream)
            .collect(Collectors.toList());

for example:

    Map<String, Map<Integer, List<Integer>>> source = Map.of("keyA", Map.of(1, Arrays.asList(1,2,3,5)), "keyB", Map.of(2, Arrays.asList(5,6,7,8)));

Output:

[5, 6, 7, 8, 1, 2, 3, 5]

Sign up to request clarification or add additional context in comments.

1 Comment

Just wanna add that the comment about key named "keya" is not accurate.
1

If the keys of the inner map should be filtered, this can be done like this:

static List<Integer> findByKey(Map<String, Map<String, List<Integer>>> map, String key) {
    return map.values()
              .stream() // Stream<Map<String, List<Integer>>>
              .flatMap(v -> v.entrySet().stream()) // Stream<Map.Entry<String, List<Integer>>>
              .filter(e -> key.equals(e.getKey()))
              .flatMap(e -> e.getValue().stream()) // Stream<Integer>
              .collect(Collectors.toList());
}

Test

Map<String, Map<String, List<Integer>>> map = Map.of(
    "KeyA", Map.of("keya", Arrays.asList(1, 2, 3)),
    "KeyB", Map.of("keya", Arrays.asList(4, 5, 6)),
    "KeyC", Map.of("keyb", Arrays.asList(7, 8))
);

System.out.println(findByKey(map, "keya"));

Output changes randomly

[4, 5, 6, 1, 2, 3]
or 
[1, 2, 3, 4, 5, 6]

This output occurs randomly the mixed order, because the input map is not sorted and this can be resolved by sorting the stream of entrySet of the input map:

static List<Integer> findByKeySorted(Map<String, Map<String, List<Integer>>> map, String key) {
    return map.entrySet()
              .stream() // Stream<Map.Entry<String, Map<List<Integer>>>>
              .sorted(Map.Entry.comparingByKey())
              .map(e -> e.getValue().get(key)) // Stream<List<Integer>>
              .filter(Objects::nonNull)
              .flatMap(List::stream) // Stream<Integer>
              .collect(Collectors.toList());
}

System.out.println(findByKeySorted(map, "keya"));

Output (stable):

[1, 2, 3, 4, 5, 6]

Comments

0

You can do it like this:

List<Integer> list = m
                .values()
                .stream()
                .flatMap(innerMap ->
                        innerMap
                        .entrySet()
                        .stream()
                        .filter(entry -> entry.getKey().equals(1))
                        .flatMap(entry -> entry.getValue().stream()))
                .collect(Collectors.toList());

Comments

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.