Поведение карты не указывается, если значение объекта изменяется способом, который влияет на сравнение на равных, а объект (изменяемый) является ключом. Даже для Set также использование изменяемого объекта в качестве ключа не очень хорошая идея.
Давайте посмотрим пример здесь:
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;
}
}
Здесь мы пытаемся добавить изменяемый объект «Сотрудник» на карту. Это будет работать хорошо, если все добавленные ключи различны. Здесь я переопределил equals и hashcode для класса сотрудника.
Смотрите, сначала я добавил "е", а затем "е1". Для обоих из них equals () будет истинным, а хеш-код будет одинаковым. Таким образом, карта видит, как будто добавляется тот же ключ, поэтому она должна заменить старое значение значением e1. Затем мы добавили e2, e3, e4 у нас все в порядке.
Но когда мы меняем значение уже добавленного ключа, т. Е. "E2", как единое целое, оно становится ключом, подобным добавленному ранее. Теперь карта будет вести себя как проводная. В идеале e2 должен заменить существующий тот же ключ, т. Е. E1. Но теперь карта принимает и это. И вы получите это в 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
См. Здесь обе клавиши, имеющие одну и ту же величину. Так что это неожиданно. Теперь снова запустите ту же программу, изменив e2.setName("diffnt");
, который здесь e2.setName("one");
... Теперь o / p будет таким:
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
Таким образом, добавление изменения изменяемого ключа на карте не рекомендуется.