3

I am trying to convert Map<String, NavigableMap<Long, Collection<String>>> into List<String> Java 8.

I wrote some code but got stuck some where in mid.

userTopics.values().stream().map(
    new Function<NavigableMap<Long, Collection<String>>, Collection<String>>() {
        @Override
        public Collection<String> apply(NavigableMap<Long, Collection<String>> t) {
            return null;  //TODO
        }
    }
);
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
cody123
  • 2,040
  • 24
  • 29

2 Answers2

4

Just flatMap that s**t:

List<String> values = nestedMap.entrySet()
        .stream()
        .map(Map.Entry::getValue)
        .flatMap(m -> m.entrySet().stream())
        .map(Map.Entry::getValue)
        .flatMap(Collection::stream)
        .collect(toList());

As Holger points out, this is neater:

List<String> values = nestedMap.values()
        .stream()
        .flatMap(m -> m.values().stream())
        .flatMap(Collection::stream)
        .collect(toList());
Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
  • 3
    A funny anti-pattern, even twice. `entrySet().stream().map(Map.Entry::getValue)` instead of streaming over the desired items in the first place: `values().stream()` – Holger Feb 28 '16 at 12:46
  • 1
    @cody123: it's the same as `.map(entry -> entry.getValue())` with `entry` being of type `Map.Entry`. When you also need the keys in an intermediate stream operation, streaming over the entries via `entrySet().stream()` and mapping to the values once a stream of values is needed, is the right solution. However, when you need the values *only*, you can right stream over the values in the first place. – Holger Feb 28 '16 at 13:24
3

Two flatMaps will do, flat the NavigableMap and then flat the Collection inside.

List<String> result = mapOfMaps.values()
            .stream()
            .flatMap(v -> v.values().stream())
            .flatMap(Collection::stream)
            .collect(Collectors.toList());
Sleiman Jneidi
  • 22,907
  • 14
  • 56
  • 77