根据前面两篇的介绍,我们知道了HashMap底层存放和查找元素的方式,因此得出了不能更改map 中key值的属性(当然是指重写了equals和hashcode的情况下)
还是使用前面的Address类
public static void main(String[] args)
{
HashMap<Address, String> map = new HashMap<Address, String>();
Address a1 = new Address("shanghai");
map.put(a1, "hello");
Address ad = null;
for(Iterator<Address> iter = map.keySet().iterator(); iter.hasNext();)
{
ad = iter.next();
}
//更改了属性值之后当前存放的key对象的hashcode值和其在底层数组中的index就关联不起来了,这样在下次无论
//是使用原来的值还是现在的值都无法定位到这个位置上来了。
ad.setDetail("beijing");
String value = map.get(new Address("shanghai"));
//value为null
System.out.println(value);
String value2 = map.get(new Address("beijing"));
//value2同样为null
System.out.println(value2);
}
因为HashSet底层就是一个HashMap,所以同样应该在HashSet中注意:
对于已经加入到容器中的元素,不应该随意更改其field属性,这将会导致在HashSet中产生两个相等(equals返回true,hashcode相等)的两个对象,并且更改后的对象无法准确的被定位到。
同样的规则其实在TreeSet中也是存在的,我们知道TreeSet中的元素的存放位置是根据其compareTo方法计算出的位置,但是当我们把一个对象放入了这个TreeSet中后,
又更改了其field属性,而且这个field属性影响到了compareTo的结果(这是很普遍的情况,因为compareTo和equals总是保持一致的,equals为true,compareTo总是应该为0,equals关联的field应该是等于或者多于compareTo的),改变了compareTo的结果后TreeSet并不会重写定位对象的位置,所以就可能产生两个equals的对象或者说大的对象在小的对象前面的情况。
总之,在set和map的key中,已经放入到容器中的对象的field是不能随便去修改的。