hashcode和equals重写规则

来源:互联网 发布:老版本mac如何升级系统 编辑:程序博客网 时间:2024/05/18 02:50

HashSet

  HashSet底层是HashMap实现的。

因此HashSet无序不可重复,也就意味着存放到HashSet中的对象元素是经过排序比较的。

如何比较呢?

1.HashMap底层是根据hashcode和equals来存放对象的。

2.我们知道Object父类中的hashcode方法默认返回的是对象的地址值,因此如果不重写hashcode,那么默认比较的是存放到集合中的对象的地址值,那么通过new出的对象,即使元素相同,也会被当做不同的元素而被HashSet去重,达不到我们想要的目的。

因此,要想根据我们的想法来实现对对象的去重,就需要我们重写放入到HashSet中的自定义对象元素,只有HashSet有此需要。

如何重写Hashcode和equals?

如何去合理的计算出一个不容易重复的hashcode?equals的比较是根据哪个属性来比较?int和String一般是怎么比较的?其他的基本类型或是引用类型呢?是不是感觉有点难度?

幸运的,一般HashCode 和equals的重写,系统已经提供好了一种简单通用的写法,我们直接重写即可。


我们新建一个MusicBox类,源码如下:public class MusicBox {// 歌手private String person;// 歌名private String name;// 大小private double lenght;public MusicBox() {super();}public MusicBox(String person, String name, double lenght) {super();this.person = person;this.name = name;this.lenght = lenght;}public String getPerson() {return person;}public void setPerson(String person) {this.person = person;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getLenght() {return lenght;}public void setLenght(double lenght) {this.lenght = lenght;}@Overridepublic String toString() {return "MusicBox [person=" + person + ", name=" + name + ", lenght=" + lenght + "]";}@Overridepublic int hashCode() {final int prime = 31;int result = 1;long temp;temp = Double.doubleToLongBits(lenght);result = prime * result + (int) (temp ^ (temp >>> 32));result = prime * result + ((name == null) ? 0 : name.hashCode());result = prime * result + ((person == null) ? 0 : person.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;MusicBox other = (MusicBox) obj;if (Double.doubleToLongBits(lenght) != Double.doubleToLongBits(other.lenght))return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;if (person == null) {if (other.person != null)return false;} else if (!person.equals(other.person))return false;return true;}}

可以看到系统为我们提供好的hashcode和equals方法,不用我们去重复的编写代码。

但是系统提供的也有缺点,那就是不能完全恰好满足我们实际的需要,因为太通用了。

比如我们想根据歌曲名称去重,而不是所有的属性,怎么办呢?解决办法有两种:

1.   我们自己修改生成的代码来满足我们的需求。

我们可以把上面的hashcode()和equals方法重写成:

@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;MusicBox other = (MusicBox) obj;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}

这样,当hashcode相同时,如果对象name比较 equals相同,那么就会去重,也就达到了我们的目的。

2.   自动生成时选择我们的需求。

我们可以不用为所有编写的属性重写hashcode和equals,而是只重写我们需要的。


也可以达到相同的目的。

具体调试内容不再粘贴。





原创粉丝点击