I've been using Guava's ImmutableMap
with a Builder
for awhile without giving much thought to how/why it works. I've been using the builder in the way described by the Javadoc:
ImmutableMap<String, Integer> WORD_TO_INT =
new ImmutableMap.Builder<String, Integer>()
.put("one", 1)
.put("two", 2)
.put("three", 3)
.build();
I've also seen examples elsewhere on SO of this syntax:
ImmutableMap<String,Integer> myMap = ImmutableMap.<String, Integer>builder()
.put("one", 1)
.put("two", 2)
.put("three", 3)
.build();
Both seem to produce the exact same result.
A quick glance at the ImmutableMap
source shows that the static builder()
call in the 2nd example returns: new Builder<K, V>()
There doesn't appear to be any functional difference between the two methods.
Is there any difference under the hood? Any reason to prefer one or the other?
EDIT: Adding bytecode difference.
The bytecode generated is almost identical except for one line:
Method 1(Builder<K,V>
):
static {};
0 new com.google.common.collect.ImmutableMap$Builder [12]
3 dup
4 invokespecial com.google.common.collect.ImmutableMap$Builder() [14]
7 ldc <String "key1"> [17]
........
Method 2:(<K,V>builder()
)
static {};
0 invokestatic com.google.common.collect.ImmutableMap.builder() : com.google.common.collect.ImmutableMap$Builder [12]
3 ldc <String "key1"> [18]
........
After that they're pretty much the same, the first line being different makes sense given the source differences, but I'm not sure why the first one calls dup
and the second doesn't.
You can simply create a new HashMap from the existing Map using the copy constructor. HashMap<String, Object> = new HashMap<>(immutableMap);
No, they are identical. The reason for the first syntax is that it makes a nice one-liner.
The reason for the second syntax is the you might have a loop or other flow control, you may need to pass the Builder
around.
For example:
public static void main(final String[] args) throws Exception {
final ImmutableList.Builder<Integer> lb = ImmutableList.builder();
for (final String arg : args) {
lb.add(Integer.parseInt(arg));
}
}
And before you say it, yes a FluentIterable
would probably be better in this case - but it's just an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With