java中equals和hashCode方法浅解
网上一搜equals和hashCode全是详解,深入剖析,巴拉巴拉。都写的非常详细,能学到很多东西。写这个就为了表达一下自己的理解,以及需要理解的程度。
刚学java,都是说字符串不能用==比较相等,要用equals,其实就是说对于引用类型的比较不能直接用==比较是否相等,因为比较的是对对象的地址,而我们期望的往往是对象内的属性值相等。
当我们自定义的类使用equals比较的时候,基本是没用,还是比较的地址,也即是equals默认就是使用==来比较的。那么问题来了,什么时候需要重写equals方法呢?以及该怎么重写呢?
很简单,就是当我们在set或者map的key使用自定义类的时候,怎么样对对象去重,就是根据equals和hashCode方法来的,这就是为什么很多人都说,重写equals方法必须要重写hashCode方法。
那么equals和hashCode究竟应该怎么重写,有什么要求吗?当然有,java规定是,equals相等时,hashCode必须相等,而并不要求hashCode相等时,equals必须相等。为什么要有这么规定,其实是和set以及map的结构有关系,set和map底层都有一个hash表,其实就是一个数组,添加一个新元素进来的,先用hashCode计算hash值,然后用hash表的长度取模,这样就相当于找到了这个元素应该放入的位置。这就是为什么equals相等时,hashCode必须相等,否则hashCode不相等,如果进入到其他位置了,岂不是就出现重复元素了。但是还有问题就是,假如两个不同元素如果hashCode相等了呢,又或者说假如两个对象经过hahs算法以后最终进入到同一个位置的时候,是第二个覆盖第一个还是怎么着?当然不会随便覆盖,这时候,如果有多个元素经过hash算法到同一个位置的时候,来一个元素,首先和位置的已有元素使用equals进行比较,如果相等,则会覆盖,如果不相等,则会加进去。
刚说加进去,怎么加进去的呢?当然是每个hash表的位置元素都是一个链表呀,来一个不重复的就在链表后加一个元素,这也就是hashmap的底层其实数组加链表的结构,hashset相当于只用了hashmap的key,到底什么意思,其实hashmap的底层是一个node类型的数组,node包含了key和value还有一个node类型next,hashset相当于只用了hashmap中node中的key,value设置成一个不变的对象,所有key都是同一个value,因为用不到,至于next还是一样的用。
上一篇: java泛型集合