Are mutable hashmap keys a dangerous practice?

后端 未结 7 1164
鱼传尺愫
鱼传尺愫 2020-11-22 06:58

Is it bad practice to use mutable objects as Hashmap keys? What happens when you try to retrieve a value from a Hashmap using a key that has been modified enough to change

相关标签:
7条回答
  • 2020-11-22 08:00

    Behaviour of a Map is not specified if value of an object is changed in a manner that affects equals comparision while object(Mutable) is a key. Even for Set also using mutable object as key is not a good idea.

    Lets see a example here :

    public class MapKeyShouldntBeMutable {
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Map<Employee,Integer> map=new HashMap<Employee,Integer>();
    
        Employee e=new Employee();
        Employee e1=new Employee();
        Employee e2=new Employee();
        Employee e3=new Employee();
        Employee e4=new Employee();
        e.setName("one");
        e1.setName("one");
        e2.setName("three");
        e3.setName("four");
        e4.setName("five");
        map.put(e, 24);
        map.put(e1, 25);
        map.put(e2, 26);
        map.put(e3, 27);
        map.put(e4, 28);
        e2.setName("one");
        System.out.println(" is e equals e1 "+e.equals(e1));
        System.out.println(map);
        for(Employee s:map.keySet())
        {
            System.out.println("key : "+s.getName()+":value : "+map.get(s));
        }
    }
    
      }
     class Employee{
    String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public boolean equals(Object o){
        Employee e=(Employee)o;
        if(this.name.equalsIgnoreCase(e.getName()))
                {
            return true;
                }
        return false;
    
    }
    
    public int hashCode() {
        int sum=0;
        if(this.name!=null)
        {
        for(int i=0;i<this.name.toCharArray().length;i++)
        {
            sum=sum+(int)this.name.toCharArray()[i];
        }
        /*System.out.println("name :"+this.name+" code : "+sum);*/
        }
        return sum;
    
    }
    
    }
    

    Here we are trying to add mutable object "Employee" to a map. It will work good if all keys added are distinct.Here I have overridden equals and hashcode for employee class.

    See first I have added "e" and then "e1". For both of them equals() will be true and hashcode will be same. So map sees as if the same key is getting added so it should replace the old value with e1's value. Then we have added e2,e3,e4 we are fine as of now.

    But when we are changing the value of an already added key i.e "e2" as one ,it becomes a key similar to one added earlier. Now the map will behave wired. Ideally e2 should replace the existing same key i.e e1.But now map takes this as well. And you will get this in o/p :

     is e equals e1 true
    {Employee@1aa=28, Employee@1bc=27, Employee@142=25, Employee@142=26}
    key : five:value : 28
    key : four:value : 27
    key : one:value : 25
    key : one:value : 25
    

    See here both keys having one showing same value also. So its unexpected.Now run the same programme again by changing e2.setName("diffnt"); which is e2.setName("one"); here ...Now the o/p will be this :

     is e equals e1 true
    {Employee@1aa=28, Employee@1bc=27, Employee@142=25, Employee@27b=26}
    key : five:value : 28
    key : four:value : 27
    key : one:value : 25
    key : diffnt:value : null
    

    So by adding changing the mutable key in a map is not encouraged.

    0 讨论(0)
提交回复
热议问题