2

I am currently working with a prefilled Hashmap, but I cannot come up with an efficient way to declare a Hashmap instantly. One way I can do it is:

static final LinkedHashMap<String, Integer> test = new LinkedHashMap<String, Integer>() {{

}}

But I was told that this way is not good because of runtime etc.. I need a way though, to fill the List instantly and not in a method, because the method where I need it is accessed multiple times.

Mal
  • 31
  • 1
  • 1
  • 4
  • 1
    You can use a static initializer for your class ( `static { /* your code here */ }` ) or you can use *lazy instantiation*. Note that final doesn't say much for collections, you'd make an final *immutable* field instead. – Maarten Bodewes Jun 21 '21 at 12:45
  • AFAIK using a static block would be the best approach – Thiyagu Jun 21 '21 at 12:47
  • What are you accessing multiple times? And there isn't a fill the List instantly method really. – matt Jun 21 '21 at 13:00

4 Answers4

4

Use java.util.Map#of() from Java 9+

static final Map<String, Integer> map = Map.of(
    "key1", 42,
    "key2", 69
);

If you specifically want a HashMap, use just that as a wrapper: new HashMap(Map.of(...))

neu242
  • 15,796
  • 20
  • 79
  • 114
  • 6
    That's *usually* a good way to initialize maps, but unfortunately [Unmodifiable Maps](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Map.html#unmodifiable) are documented with this sentence: "The iteration order of mappings is unspecified and is subject to change.". That's no good, if OP wanted to use a `LinkedHashMap`, supposedly in order to maintain insertion order. – Joachim Sauer Jun 21 '21 at 12:55
  • 1
    @JoachimSauer but op's description they say they're using a hashmap so it doesn't soundlike the "LinkedHashMap" part is relevant. – matt Jun 21 '21 at 12:59
  • 1
    Hmm, it does explicitly use a `SortedMap` implementation though. – Maarten Bodewes Jun 21 '21 at 13:57
3

You can always do something like this:

static LinkedHashMap<String, Integer> test;

static {
  test = new LinkedHashMap<String, Integer>()
  test.put("key", 1);
  //etc
}

If you need it to be final then initialize it inline and fill the data in static block;

gawi
  • 2,843
  • 4
  • 29
  • 44
1

You can have a method for loading the map

static final Map<String, Integer> TEST = loadTest();

private static Map<String, Integer> loadTest() {
    Map<String, Integer> ret = new LinkedHashMap<>();
    // populate the map.
    return ret;
}

Another way to load the data lazily

static final Map<String, Integer> TEST = new LinkedHashMap<>();

static Integer getTest(String key) {
    return TEST.computeIfAbsent(key, k -> valueForKey(k));
}

static int valueForKey(String key) {
    // load one value, only called once per key
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    I'd use a separate local map variable and then only assign `Collections.unmodifiableMap(tempVar)` at the end of the static block. – Maarten Bodewes Jun 21 '21 at 12:52
  • 1
    Uh, or the unmodifiable [`SortedMap`](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableSortedMap-java.util.SortedMap-) version of it of course. – Maarten Bodewes Jun 21 '21 at 13:58
  • 1
    @MaartenBodewes ideally I wouldn't even expose the Map, rather a method like `getTest(key)` – Peter Lawrey Jun 22 '21 at 09:18
  • 1
    Yeah, and if you want order you can return an iterator over the keys I suppose. I'd even try and refrain from using `static`, but maybe that's a bridge too far in this case. – Maarten Bodewes Jun 22 '21 at 09:59
1

and not in a method, because the method where I need it is accessed multiple times.

That is a misconception.

static final LinkedHashMap singleton = createMap();

//called once.
private static LinkedHashMap<K,V> createMap(){
    //create and return map.
}

public LinkedHashMap<K, V> getMap(){
    return new LinkedHashMap<>(singleton);
}

The creation code is called once, and the map is accessed multiple times.

matt
  • 10,892
  • 3
  • 22
  • 34