CuriousCoder
CuriousCoder

Reputation: 1600

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?

Upvotes: 6

Views: 1905

Answers (2)

Andy Turner
Andy Turner

Reputation: 140534

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));
}

Upvotes: 8

Arvind Kumar
Arvind Kumar

Reputation: 609

Just put a filter before collecting into map

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

       doSomethingWithThisMap(map);
    }

Upvotes: -1

Related Questions