Creating a HashMap with entries
Problem: Create an instance of HashMap in Java with entries in it. I don't want to create a new HashMap instance and keep adding entries to it. I want to have a concise way of creating a HashMap with entries.
Solution: Guava library comes with factory methods that can create a HashMap without using the verbose form of "Map myMap = new HashMap()". You can simply say "Map myMap = newHashMap()", assuming you have done a static import of the Maps.newHashMap method. But that is not sufficient. It would be better to provide a utility method that looks like this: "Map myMap = newHashMapWithEntries(firstKey, firstValue, secondKey, secondValue)". That way it is easy to create static-final maps instead of writing a separate method to populate them or to populate them from constructor, as given below:
That is too verbose. What I want is something like:
So here is one possible implementation of newHashMapWithEntries:
Solution: Guava library comes with factory methods that can create a HashMap without using the verbose form of "Map
public class MyClass {
private static final Map<String, URL> serviceUrls = createServiceUrlsMap();
private static Map<String, String> createServiceUrlsMap() {
Map<String, URL> retVal = new HashMap<String, URL>();
retVal.put("google", new URL("http://www.google.com");
retVal.put("yahoo", new URL("http://www.yahoo.com");
return retVal;
}
}
That is too verbose. What I want is something like:
public class MyClass {
private static final Map<String, URL> serviceUrls = newHashMapWithEntries(
"google", new URL("http://www.google.com"),
"yahoo", new URL("http://www.yahoo.com"));
}
So here is one possible implementation of newHashMapWithEntries:
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> newHashMapWithEntries(K firstKey, V firstValue, Object... rest) {
if(rest.length%2 != 0) {
throw new IllegalArgumentException("Expected the number of args to be even.");
}
Class<? extends Object> keyType = firstKey.getClass();
Class<? extends Object> valueType = firstValue.getClass();
Map<K, V> retVal = new HashMap<K, V>();
retVal.put(firstKey, firstValue);
for(int i = 0; i < rest.length; i += 2) {
if(!keyType.isAssignableFrom(rest[i].getClass())) {
throw new IllegalArgumentException("Expected all keys to be of type <? extends " +
keyType.getName() + ">, but found " + rest[i].getClass().getName() + ".");
}
if(!valueType.isAssignableFrom(rest[i+1].getClass())) {
throw new IllegalArgumentException("Expected all values to be of type <? extends " +
valueType.getName() + ">, but found " + rest[i+1].getClass().getName() + ".");
}
retVal.put((K)rest[i], (V)rest[i+1]);
}
return retVal;
}
Comments
why not use google collections library, e.g:
ImmutableMap map = new ImmutableMap.Builder()
.put("one", 1)
.put("two", 2)
.build();
cheers
Why not doing it in this way:
private static final Map serviceUrls = new HashMap();
static {
serviceUrls.put("google", new URL("http://www.google.com"));
serviceUrls.put("yahoo", new URL("http://www.yahoo.com"));
}
(The MalformedURLException must be catched)
In Scala you can create Maps this way:
var steps = Map (1 -> "Go straight on", 2 -> "Take the second turn on the left", 3 -> "It's opposite the hairdresser")
ImmutableMap map = ImmutableMap.of("key", "val", "key1", "val2");
Except, with an extra factory method, the type checks and illegalargumentexception can be removed:
public class MyClass {
public static <K, V> Map<K, V> newHashMapWithEntries(Map.Entry<K, V>... entries) {
Map<K, V> map = new HashMap<K, V>();
if (entries != null) {
for (Entry<K, V> entry : entries) {
map.put(entry.getKey(), entry.getValue());
}
}
return map;
}
public static <K, V> Map.Entry<K, V> entry(K k, V v) {
return new AbstractMap.SimpleEntry<K, V>(k, v);
}
public static void main(String[] args) throws Exception {
Map<String, URL> serviceUrls =
newHashMapWithEntries(
entry("google", new URL("http://www.google.com")),
entry("yahoo", new URL("http://www.yahoo.com"))
);
}
}
final private static Map SERVICE_URLS = Collections.unmodifiableMap(new HashMap() {{
try {
put("google", new URL("http://www.google.com"));
put("yahoo", new URL("http://www.yahoo.com"));
} catch (MalformedURLException ex) {
log.log(Level.ERROR, "", ex);
}
}});
You can also use commons-lang3 ArrayUtils toMap function to create a Map
Map map = ArrayUtils.toMap(new Object[][]{{"shekhar",1},{"rahul",2}});
But the problem is Map does not contain type information.It is a map of Objects
Thanks for this Nice artilce just to add while discussing about HashMap its worth mentioning following questions which frequently asked in Java interviews now days like How HashMap works in Java or How get() method of HashMap works in JAVA very often. on concept point of view these questions are great and expose the candidate if doesn't know deep details.
Javin
FIX Protocol tutorial