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.

Nowhere Man
19.7k9 gold badges21 silver badges45 bronze badges
asked Oct 9, 2021 at 18:36
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]

answered Oct 9, 2021 at 19:01

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]
answered Oct 9, 2021 at 22:09

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());
answered Oct 9, 2021 at 19:14

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.