Guava provides us with great factory methods for Java types, such as Maps.newHashMap()
.
But are there also builders for java Maps?
HashM
Since Java 9 Map interface contains:
Map.of(k1,v1, k2,v2, ..)
Map.ofEntries(Map.entry(k1,v1), Map.entry(k2,v2), ..)
. Limitations of those factory methods are that they:
null
s as keys and/or values (if you need to store nulls take a look at other answers)If we need mutable map (like HashMap) we can use its copy-constructor and let it copy content of map created via Map.of(..)
Map<Integer, String> map = new HashMap<>( Map.of(1,"a", 2,"b", 3,"c") );
You can use the fluent API in Eclipse Collections:
Map<String, Integer> map = Maps.mutable.<String, Integer>empty()
.withKeyValue("a", 1)
.withKeyValue("b", 2);
Assert.assertEquals(Maps.mutable.with("a", 1, "b", 2), map);
Here's a blog with more detail and examples.
Note: I am a committer for Eclipse Collections.
A simple map builder is trivial to write:
public class Maps {
public static <Q,W> MapWrapper<Q,W> map(Q q, W w) {
return new MapWrapper<Q, W>(q, w);
}
public static final class MapWrapper<Q,W> {
private final HashMap<Q,W> map;
public MapWrapper(Q q, W w) {
map = new HashMap<Q, W>();
map.put(q, w);
}
public MapWrapper<Q,W> map(Q q, W w) {
map.put(q, w);
return this;
}
public Map<Q,W> getMap() {
return map;
}
}
public static void main(String[] args) {
Map<String, Integer> map = Maps.map("one", 1).map("two", 2).map("three", 3).getMap();
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
This is something I always wanted, especially while setting up test fixtures. Finally, I decided to write a simple fluent builder of my own that could build any Map implementation - https://gist.github.com/samshu/b471f5a2925fa9d9b718795d8bbdfe42#file-mapbuilder-java
/**
* @param mapClass Any {@link Map} implementation type. e.g., HashMap.class
*/
public static <K, V> MapBuilder<K, V> builder(@SuppressWarnings("rawtypes") Class<? extends Map> mapClass)
throws InstantiationException,
IllegalAccessException {
return new MapBuilder<K, V>(mapClass);
}
public MapBuilder<K, V> put(K key, V value) {
map.put(key, value);
return this;
}
public Map<K, V> build() {
return map;
}
There's ImmutableMap.builder()
in Guava.
HashMap
is mutable; there's no need for a builder.
Map<String, Integer> map = Maps.newHashMap();
map.put("a", 1);
map.put("b", 2);