Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java HashMap - Is it necessary to use .put() for each set? [duplicate]

Tags:

java

hashmap

Imagine the following scenario. You have a set of values which are already accessible and known. You have to put them into a HashMap for reasons.

Code example:

String a = "a";
Strinb b = "b";
...
HashMap map = new HashMap(5);
map.put("a", a);
map.put("b", b);
...

Is it really necessary to do it like this? I can't believe that there is not a constructor which let you put in your values from scratch.

I'm talking about something like this:

HashMap map = new HashMap(<"a", a>, <"b", b>, ...);

Or even something like this:

HashMap map = new HashMap(5);
HashMap.putBunchOfStuff("a", a, "b", b, ...);

Edit: My intention was to ask if there is a method but more importantly, if the answer is "no", why there isn't such a constructor/method.

like image 237
OddDev Avatar asked May 06 '15 14:05

OddDev


People also ask

What happens if we put duplicate key in HashMap?

HashMap stores key, value pairs and it does not allow duplicate keys. If the key is duplicate then the old key is replaced with the new value.

Does HashMap allow duplicate elements?

HashMap is similar to HashTable, but it is unsynchronized. It allows to store the null keys as well, but there should be only one null key object and there can be any number of null values. This class makes no guarantees as to the order of the map. To use this class and its methods, you need to import java.

What happens when we attempt to add a duplicate key to a map using put?

What will happen if we attempt to add duplicate values ? Ans. No, We cannot have duplicate keys in HashMap. If we attempt to do so , the previous value for the key is overwritten.


2 Answers

Unfortunately, collection literals were a proposal for Project Coin in Java 7 (and Java 8), but it never made it into the final product, aka it is not a feature of Java.

The proposition was this

Here’s how it would look with map literals:


    final Map<Integer, String> platonicSolids = { 
          4 : "tetrahedron",
          6 : "cube", 
          8 : "octahedron", 
          12 : "dodecahedron", 
          20 : "icosahedron"
    };


Here is the empty map literal, which has a slightly irregular syntax to make
it differ from the empty set:


    Map<String, Integer> noJokeHere = { : };

BUT it never happened, so unfortunately that doesn't work. So unless you write your own magic builder or fancy lambda like on this site of Per-Åke Minborg, you're on your own. The following from the site should work, though (in Java 8).

//copy paste from linked site
Map<Integer, String> map = Stream.of(
            new SimpleEntry<>(0, "zero"),
            new SimpleEntry<>(1, "one"),
            //...
            new SimpleEntry<>(11, "eleven"),
            new SimpleEntry<>(12, "twelve"))
            .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()));

And the simplified version, also from the site:

//copy paste from linked site
public static <K, V> Map.Entry<K, V> entry(K key, V value) {
    return new AbstractMap.SimpleEntry<>(key, value);
}

public static <K, U> Collector<Map.Entry<K, U>, ?, Map<K, U>> entriesToMap() {
    return Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue());
}

Map<Integer, String> map = Stream.of(
            entry(0, "zero"),
            //...
            entry(12, "twelve"))
            .collect(entriesToMap());

Collection literals weren't introduced because of these points:

  • The "simple" version of this feature (sets, lists, maps only) is not very satisfying or popular; the "extensible" version of this feature is open-ended, messy, and virtually guaranteed to way overrun its design budget;

  • The library-based version gives us X% of the benefit for 1% of the cost, where X >> 1;

  • Value types are coming, and the "what would this feature look like" in a world with value types may well be quite different than in a world without, suggesting it would be questionable to try and do this work before value types;

  • We are better off focusing our language-design bandwidth on addressing more the foundational issues underlying a library-based version (including: more efficient varargs, array constants in the constant pool, immutable arrays, and support for caching (and reclaiming under pressure) intermediate immutable results).

By Brian Goetz from Oracle

like image 180
EpicPandaForce Avatar answered Oct 13 '22 21:10

EpicPandaForce


There's no such constructor by default - you could use the double-brace idiom to put all values in the map on instantiation, but this still requires multiple put calls:

Map<String,String> map = new HashMap<>() {{
    put("a", "val1");
    put("b", "val2");
    //etc.
}};

In reality you usually have large blocks of data you want to put into a map accessible from a stream or another collection, so it's trivial to loop over multiple put calls in this instance.

Guava has a putAll() on its ImmutableMap.Builder, enabling you to do something similar to this before instantiation. Other external libraries may have other similar behaviour, but fact is you'll have to resort to using external libraries.

like image 45
Michael Berry Avatar answered Oct 13 '22 22:10

Michael Berry