Java Streams and IDE Weirdness (part 2)

Brian Olson
Nov 9, 2020

I recently posted about some IDE weirdness when trying to use java streams. Not long after I encountered some more! This time using Google’s Guava collectors, specifically ImmutableMap.

Immutability is the concept of having objects that cannot change. It can add confidence to your programming approach by letting you know objects will always be consistent — no values will change out from under you because someone else has a reference to the object.

But yet again you get some weirdness by pushing some dynamic typing and functions as first class objects into Java. Let’s look at this example

ImmutableMap<String, String> sourceMap = ImmutableMap.of("key1", "value1",
"key2", "value2");
ImmutableMap<String, String> destMap = sourceMap.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue
));

Seems pretty reasonable, but some of you might be able to spot the mistake already. Here’s the error I got

This isn’t too bad. In a couple other IDEs (that I won’t name) I got more cryptic errors about not being able to access non-static methods from static methods. The confusing part is the generics on the map. It makes it look like it’s losing track of generics of the map created above.

The fix is to use ImmutableMap.toImmutableMap() like this

ImmutableMap<String, String> destMap = sourceMap.entrySet()
.stream()
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));

And suddenly all of the type arguments line up!

My key take aways here are

  1. Anytime you see this many generics in a javadoc slow way down to make sure you understand what’s happening public static <T,K,V> Collector <T,?,ImmutableMap<K,V>>
  2. Use as specific of a stream collector as you can
  3. When in doubt (or extreme need) revert to a good ol’ for loop

--

--

Brian Olson

Engineer, formerly at Amazon, currently at Google. All opinions are my own. Consider supporting here: https://devblabs.medium.com/membership