Alexx Shadenk
Alexx Shadenk

Reputation: 21

HashMap of ArrayList<String>, String is not working properly?

So , I want to make a map of Lists of Strings to Strings, but I cannot get it to work properly:

this is all the code I have done, and until i can find out why, I cannot progress:

Map<List<String>, String> test = new HashMap<List<String>, String>();
test.put( new ArrayList<String>(), "s1");
test.put( new ArrayList<String>(), "s2");
test.put( new ArrayList<String>(), "s3");

System.out.println(test.size());

i get 1, it should be 3!! Why is only one object getting added when I made 3 calls, for 3 separate objects? I know the danger of accidentally adding in the same object to a collection, but I specifically created a new ArrayList for each put, thus creating a total brand new object.

So why is there only one object in the Map then? Thanks!

Upvotes: 2

Views: 1844

Answers (5)

scott
scott

Reputation: 974

I'm not sure why you need the list as the key and the string as the value, but you are basically using the same 'key' for each put operation since the hashcode is the same for any empty list. Like the other answers mention, it's probably best to switch the list as the value and the string as the key. If the list changes, any future attempts at .get will return null

   public static void main(String...args) {
       Map<List<String>, String> test = new HashMap<List<String>, String>();
       List<String> bob = new ArrayList<>();
       bob.add("asdf");
       test.put( new ArrayList<String>(), "s1");
       test.put( bob, "s2");

       System.out.println(test.size());
       System.out.println(test.get(bob));
   }

outputs

2
s2

When a new item gets added like

   public static void main(String...args) {
       Map<List<String>, String> test = new HashMap<List<String>, String>();
       List<String> bob = new ArrayList<>();
       bob.add("asdf");
       test.put( new ArrayList<String>(), "s1");
       test.put( bob, "s2");      
       bob.add("aabbcc");

       System.out.println(test.size());
       System.out.println(test.get(bob));
   }

The get will not work, since the hash of the list has changed. The output in this case would be:

2
null

Upvotes: 0

Sam
Sam

Reputation: 2452

The best approach would be to use the String object as key and the List as value.

Have a look at what java docs say here.

And if at all you want to add the ArrayList as key then overriding equals method should suffice.

The post here gives good insights. I have put some which I liked from that post.

Overriding equals for two ArrayLists:

 public boolean equals(List<String> one, List<String> two){
    if (one == null && two == null){
        return true;
    }

    if((one == null && two != null) 
      || one != null && two == null
      || one.size() != two.size()){
        return false;
    }

    //to avoid messing the order of the lists we will use a copy
    //as noted in comments by A. R. S.
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two);   

    Collections.sort(one);
    Collections.sort(two);      
    return one.equals(two);
}

Upvotes: 0

dreamcrash
dreamcrash

Reputation: 51593

Try this:

Map<String,List<String>> test = new HashMap<String,List<String>>();
test.put("s1", new ArrayList<String>());
test.put("s2", new ArrayList<String>());
test.put("s3", new ArrayList<String>());

System.out.println(test.size());

Note that a map is a key-value relation. For this reason, you may want too use the String as a key and the ArrayList as the values, instead of the other way around. This way, if you add 3 different Strings, each one will have a different hash value (hashcode). Thus, you will have 3 different keys in your Map.

Note also that:

put

public Object put(Object key, Object value) Associates the specified value with the specified key in this map. If the map previously contained a mapping for this key, the old value is replaced.

This is why you are getting 1, instead of 3, because you were adding the same object new ArrayList<String>().

Take look in more detail into the Class HashM specifications.

Upvotes: 3

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136112

You use ArrayList as the key, try

    System.out.println(new ArrayList<String>().equals(new ArrayList<String>()));

it prints

true

Upvotes: 1

user1181445
user1181445

Reputation:

The ArrayList#hashCode() is returning the same for all of them. If you look at the sourcing for it: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/AbstractList.java#AbstractList.hashCode%28%29

You can see that should there be no elements, or all the same elements, that the hashCode would be the same.

Fix that up and it should work fine. Use either a Map or change the hashCode in one way or another.

Upvotes: 3

Related Questions