WhatTheCode
WhatTheCode

Reputation: 57

Understanding hashmap (with Arraylist as value) put method

I'm having trouble getting my head around something I encountered earlier. I have this class named DictionaryOfTranslations, which has a method called add.

The only instance variable this class has is a private HashMap<String, ArrayList<String>> dictionary;.

This is what the add method looks like:

public void add(String word, String translation) {
    this.dictionary.putIfAbsent(word, new ArrayList<>());
    
    ArrayList<String> completed = this.dictionary.get(word);
    completed.add(translation);
    this.dictionary.put(word, completed);
}

The trouble I'm having is to understand why this last line of code: this.dictionary.put(word, completed); is apparently redundant. If I comment this line out, the outcome is exactly the same. My question here is: Why don't you have to specifically have to call the put() method on this hashmap, to add the updated Arraylist to it?

Upvotes: 0

Views: 627

Answers (3)

Joop Eggen
Joop Eggen

Reputation: 109547

It is redundant because the Object value you put into the HashMap is shared.

This on the other hand means you cannot do:

// ERROR
translation = new ArrayList<>();
Collection.addAll(translation, "he", "him");
dictionary.put("li", translation);
translation.clear(); // Should have been: translation = new ArrayList<>();
Collection.addAll(translation, "she", "her");
dictionary.put("ŝi", translation);

One has to add a new List every time.

Upvotes: 1

Polygnome
Polygnome

Reputation: 7795

Objects are not passed by value, their references are.

When you use put(), the reference is stored in the HashMap. Similarly, if you use get, you do not get a copy of the list, you get a reference to the same list object.

If you mutate the Map through the reference, you mutate still the same object that is also stored in the map.

Thus, putting it back is simply not needed - you have already changed that very object.

Upvotes: 2

Andy Turner
Andy Turner

Reputation: 140309

It is redundant because of the putIfAbsent previously. You've already ensured that it's present, in order to get it, so putting it back again doesn't change anything.

Of course, this code is more verbose than it needs to be, and may unnecessarily allocate a new list. Instead:

this.dictionary.computeIfAbsent(word, k -> new ArrayList<>()).add(translation);

Upvotes: 6

Related Questions