Hash Code
在Java中,hash code(散列码)是由对象导出的一个整型值,以下是几个常见哈希值的算法:
1)Object类的hashCode()
.返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。
2)String类的hashCode()
.根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串所在的堆空间相同,返回的哈希码也相同。
3)Integer类,返回的哈希码就是Integer对象里所包含的那个整数的数值,例如Integer i1=new Integer(100
),i1.hashCode的值就是100 。由此可见,2个一样大小的Integer对象,返回的哈希码也一样。
散列码的作用是作为散列表的key,我们会在后续的集合章节中详细的讲解,我们现在只需要知道,散列的价值在于速度。
Equals和 Hashcode
这两个其实确切意义上并没有什么联系,前提是我们不会在HashSet,HashMap这种本质是散列表的数据结构中使用,如果我们要在HashSet,HashMap这种本质是散列表的数据结构中使用,在重写equals方法的同时也要重写hashCode方法,以便用户将对象插入到散列表中,否则会导致数据不唯一,内存泄漏等各种问题,具体的缘由会在集合源码分析中进行进一步的探讨。
总结:
1.hashCode是为了提高在散列结构存储中查找的效率,在线性表中没有作用。
2.equals()
和hashCode()
需要同时覆盖,而且定义必须一致,也就是说equals比较了哪些域,hashCode就会对哪些域进行hash值的处理。
3.若两个对象equals()
返回true,则hashCode()
有必要也返回相同的值。
4.若两个对象equals()
返回false,则hashCode()
不一定返回不同的值。
5.若两个对象hashCode()
返回相同的值,则equals()
不一定返回true。
6.若两个对象hashCode()
返回不同值,则equals()
一定返回false。
7.同一对象在执行期间若已经存储在集合中,则不能修改影响hashCode值的相关信息,否则会导致内存泄露问题。
toString方法
toString方法用于返回表示对象值的字符串,toString方法一般会被重写,重写的格式一般是:类名,然后是一对方括号括起来的域值。
在日常的编程中,我们应该给每一个自定义的类都添加一个toString方法,这样做有助于团队协作和代码的可读性。
例子
下面我们通过一个例子来看看如果重写Object类的equals()
,hashCode()
,toString()
:
public class Employee {
private String name;
private Double salary;
private LocalDate hireDay;
public Employee(String name, Double salary, int year, int month, int day) {
this.name = name;
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
}
public String getName() {
return name;
}
public Double getSalary() {
return salary;
}
public LocalDate getHireDay() {
return hireDay;
}
public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
}
@Override
public boolean equals(Object otherObject) {
if (this == otherObject) {
return true;
}
if (otherObject == null) {
return false;
}
if (getClass() != otherObject.getClass()) {
return false;
}
Employee other = (Employee) otherObject;
return Objects.equals(name, other.name) && Objects.equals(salary, other.salary) && Objects.equals(hireDay, other.hireDay);
}
@Override
public int hashCode() {
return Objects.hash(name, salary, hireDay);
}
@Override
public String toString() {
return getClass().getName() + "[name = " + name + ", salary = " + salary + ", hireday = " + hireDay + "]";
}
}
以及他的子类:
public class Manager extends Employee{
private double bonus;
public Manager(String name, Double salary, int year, int month, int day) {
super(name, salary, year, month, day);
bonus = 0;
}
@Override
public Double getSalary() {
double baseSalary = super.getSalary();
return baseSalary + bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public boolean equals(Object otherObject) {
if (!super.equals(otherObject)) {
return false;
}
Manager other = (Manager) otherObject;
return bonus == other.bonus;
}
@Override
public int hashCode() {
return super.hashCode() + 17 * new Double(bonus).hashCode();
}
@Override
public String toString() {
return super.toString() + "[bonus = " + bonus + "]";
}
}
公众号
扫码或微信搜索Vi的技术博客,关注公众号,不定期送书活动各种福利~