Search code examples
javajava-streamoption-typecollectors

Collectors.toMap only if optional value is present


I have a list of languages like english, french, etc. I also have a list of words like apple, orange, etc. For each word, I want to create a map that looks like this:

Map map = {english = apple, italian = mela}

In order to get the translatedWord, I have a function that returns an optional. Signature of the method looks like this:

Optional<TranslatedWord> getTranslatedWord(String word, Language language);

This is the code I have written to collect the words into a map

List<Language> languages = {english, italian, french};
for(String w : words) {
   Map<Language, TranslatedWord> map = languages.stream().collect(Collectors.ToMap(language -> language,
      language -> getTranslatedWord(w, language));

   doSomethingWithThisMap(map);
}

The problem is getTranslatedWord() returns an Optional. I need to collect it into the Map only if the optional has a value in it. How can I do this?


Solution

  • Filter before you collect:

    Map<Language, TranslatedWord> map =
        languages.stream()
            .map(lang -> new AbstractMap.SimpleEntry<>(lang, getTranslatedWord(w, lang)))
            .filter(e -> e.getValue().isPresent())
            .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().get()));
    

    However, streams don't add all that much value here. You could just use a loop:

    Map<Language, TranslatedWord> map = new HashMap<>();
    for (Language lang : languages) {
      getTranslatedWord(w, lang)
          .ifPresent(t -> map.put(lang, t));
    }