3

I'm trying to use HashMap and Hastable with a List of Object as Key. Please see below a simplified version of my code which doesn't work. When I debug this code, I expect having 3 items in the TestMap4 Object but there is only 1.

List<String> lst = new ArrayList<>();
lst.add("Hello");
lst.add("World");

Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst, 1);
testMap4.put(lst, 2);
testMap4.put(lst, 5);

What happens when I put a new item into the HashMap object ? why doesn't it work ?

I obtain the same result with this new example below. (Each List countains the same 2 String)

List<String> lst = new ArrayList<>();
lst.add("Hello");
lst.add("World");

List<String> lst2 = new ArrayList<>();
lst2.add("Hello");
lst2.add("World");

List<String> lst3 = new ArrayList<>();
lst3.add("Hello");
lst3.add("World");

Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst,1);
testMap4.put(lst2,2);
testMap4.put(lst3,5);

If I modify only 1 char of the 2 String, this is OK

3
  • you misunderstand key/value part of a map: tutorialspoint.com/java/java_hashmap_class.htm. A Map can only have 1 value, that is associated with 1 unique key. You put the values with the same key, so you override every time the existing value Commented Feb 11, 2017 at 22:49
  • What is the meating of the numbers 1, 2 and 5? Are you attempting to put the list (the same list) against the keys 1,2 and 5. If so you have your key and value the wrong way round Commented Feb 11, 2017 at 23:03
  • Is there a way to modify the Hashcode for each List of Item(s) to identify it as unique ? Commented Feb 11, 2017 at 23:13

3 Answers 3

6

You do not understand the concept of HashMap.

Your problem is that you are using the same key each time.

testMap4.put(lst, 1);     // <----same key, different value
testMap4.put(lst, 2);     // <----same key, different value
testMap4.put(lst, 5);     // <----same key, different value

In Hashmap, every value that is stored in the Hashmap, there's a key that is saved with that particular value and is unique for each value stored in Hashmap

Important points about HashMap:

1- A HashMap contains values based on the key.

2- It contains only unique elements.

3- It may have one null key and multiple null values.

4- It maintains no order.

Example

 HashMap<Integer,String> hm = new HashMap<>();  

Secondarily, using a mutable object (a List<>) as the key results in undefined behavior if any of the lists are modified after they are inserted into the map. The hash code is calculated according to the contract for List (see the Javadoc) only when the entry is first inserted into the map. A change to the list's contents will change the hash code and you will no longer be able to find the entry.

Using a List<> (or any mutable object) as the key in a HashMap<> is a Really Bad Idea™.

Sign up to request clarification or add additional context in comments.

Comments

0

It is not working because you are using same key each time for storing different value due to which all the value are getting map to same key and hashmap is only storing the last value since this value override the previous values.

Comments

0

HashMap calls the hashCode() method on the key-object you put in the HashMap.

As you don't have overridden it for the key class you use (List<> in your case) it calls the hashCode() method on java.lang.Objectwhich returns a unique object id.

As you put the same object three times into the Map, it is the same key you put in three times in a row.

List<String> lst1 = new ArrayList<>();
lst.add("Hello");
lst.add("World");
List<String> lst2 = new ArrayList<>();
List<String> lst3 = new ArrayList<>();

Map<List<String>, Integer> testMap4 = new HashMap<List<String>, Integer>();
testMap4.put(lst1, 1);
testMap4.put(lst2, 2);
testMap4.put(lst3, 5);

will give you three entries in your Map.

If you need a HashCode over the contents of the list for usage as HashMap keys, have a look at:

static int java.util.Objects.hash(Object... values)
static boolean java.util.Arrays.equals(Object[] a, Object[] a2)

Don't forget that you always have to override both methods. hashCode() and equals(). You will instantly drop dead, if you only override one of them!! ;)

3 Comments

I have extended the ArrayList<> class and overrided the hashCode() method like this : @Override public int hashCode() { return UUID.randomUUID().hashCode(); } It seems work in my case.
So this is definitely wrong!! If you return a random number, then the hashCode on a put(o, x) will be different than the hashCode on a get(o) meaning that you never will be able to retrieve your value out of the HashMap again! If you put one String into a Map as key two times, the second put would also override the first put! This is how Maps work!
I had a look into equals and compare of AbstractList and they are already implemented to give a hashCode and equals based on the contents of the List. So no need to override something unless you want to retrieve the same value, no matter how you have modified the list after you had put it in the Map. In this case I would override hashCode and Compare to call Objects equals and compare.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.