javajava-stream

Map<?, Optional<T>> to Map<?, T>


I have a Map with Optional values.

I want to filter it to remove empty values.

Map<K, Optional<T>> input;

Map<K, T> result = input.
// here is some code I'm looking for
                   .collect(Collector.toMap(???));

What is easiest way to achieve it?

All I can think of requires Optional.get and I don't like that IDE warns me about it.


Solution

  • The easiest way to do it, especially while avoiding Optional.get(), isn't going to involve streams at all; more like

    Map<K, T> result = new LinkedHashMap<>();
    input.forEach((k, vOpt) -> {
      vOpt.ifPresent(v -> result.put(k, v));
    });
    

    (In general, if there isn't a really obvious way to do something with streams, it's generally going to be simpler and cleaner not to use streams at all.)

    If you insist on using a Collector, it's possible but requires a carefully customized one, especially if you won't tolerate Optional.get().

    map.entrySet().stream()
      .collect(Collector.of(
        LinkedHashMap::new,
        (map, entry) -> entry.getValue().ifPresent(v -> map.put(entry.getKey(), v)),
        (m1, m2) -> { 
          m1.putAll(m2);
          return m1;
        }));
    

    If you can tolerate Optional.get(), you might consider it simpler to write

    map.entrySet().stream()
      .filter(e -> e.getValue().isPresent())
      .collect(Collectors.toMap(Entry::getKey, e -> e.getValue().get()));