java为什么要重写hashCode方法和equals方法?

之前发布过一篇文章说的是关于 equals方法重写 http://www.cnblogs.com/aL0n4k/p/4777333.html

 下面就hashCode方法发表一下本人的理解,仅供参考,交流.

 在 关于java重写equals方法 已经提及说,比较2个对象的时候,要比较他们各自的属性.

 那么重写hashCode方法是因为我们在接触到集合的时候,里面有个Set接口,他只能添加无序以及不重复的对象元素.

 那有人会问,既然是这样我们直接用equals判断不就完了么?

 实际上对Set集合而言,他是需要先比较对象的hashCode值的,也就是一个对象的引用地址(在内存中的存储地址)

 Set是先调用hashCode判断地址值是否一样,如果不一样则直接插入,一样则再调用equals方法判断内容是否相同,如果还相同再不插入,不相同则插入.

 重写hashCode方法就是为了和已经插入的那些元素进行具体的元素比较(这里就是故意要两个对象引用值相同,就是为了去判断2个对象属性是否一样)

 1.两个对象的地址值不一样时:那么即使他们的属性是一样的内容,也不去用equals判断,直接不插入到集合中.

 2.两个对象地址值比较相同时:再去用equals比较,然后equals比较完了还是一样的话,就不插入.不一样就插入.

 

小结:

 所以说我们要想在2个对象(内存值不一样),但是属性内容是一样 只插入其中一个的情况下可以重写hashCode方法

 重写hashCode方法就是为了让equals这个方法再去比较一下对象的属性是不是一样的,因为jdk(本人的1.8)默认提供的hashCode方法只是简单的返回2个

 对象的码值,又因为我们是通过new创建的对象引用,那么肯定是不一样的地址了,所以我们就需要重写让他2个对象都返回一样的地址值.然后判断equals方法比较具体的

 属性之后,再去决定要不要插入这个元素.

 当然更快就是为了加快插入时的检索,因为后面还需要调用equals方法进行判断.如果直接通过hashCode判断出他们地址值相等,那么就不需要去判断equals方法了.

Set插入时具体操作可以看http://blog.csdn.net/liushuai_ly/article/details/8197508

 1 import java.util.HashSet;
 2 import java.util.Set;
 3
 4 public class Test_Set {
 5
 6     public static void main(String[] args) {
 7         Person p1 = new Person("小明", 11);
 8         //假设p1是你
 9         Person p2 = new Person("小明", 11);
10         //假设p2是你同学,他也叫小明,然后他跟你年龄一样大都是11岁.
11         //那这时候我们就认定他是同一个人么?
12
13         //这是2个人没错吧?(但是相对于没有重写的hashCode他们就是2个人,可是我们这时候只需要插入一个对象,因为他们是相同的属性)
14         //那么我们就需要重写hashCode方法和Equals方法
15         //p1和p2都是通过new创建的对象引用,他们的内存值(hashCode码值)是不一样的
16         //所以即使他们的对象属性(age)都一样,也会认为他们是2个人.
17         //那么这时候我们就需要重写hashCode方法,让两个对象返回的hashCode码值都是一样的.
18         //这时候我们才去用equals方法比较他们之间各个属性,如果比较完了还是一样的.
19         //那么就表示他们是一个对象,那么我们就不往Set集合中插入后面的那个元素.
20         //如果不一样,我们就插入p2这个对象.
21         //但如果你说我没必要这样子,我就要把所有属性都一样的2个对象插到集合里面,那么你可以不重写这些东西.
22         //不重写的话,他们比较hashCode值的时候总是不同的2个对象(即使他们所有的属性都完全相同)
23
24         Set<Person> set = new HashSet<Person>();
25         set.add(p1);
26         set.add(p2);
27         //输出一下set所有的元素,看看能不能输出两个对象出来
28         System.out.println(set);
29         //本人机器输出结果为 [[email protected]]
30
31     }
32
33 }
34 class Person {
35     String name;
36     int age;
37
38
39     public Person(String name, int age) {
40         this.name = name;
41         this.age = age;
42     }
43
44
45     /*    @Override //重写hashCode
46     public int hashCode() {
47         return age + name.hashCode();
48         //返回一个固定的值,如果一样就说明地址值一样,再去equals()判断,不一样,就直接插入.
49     }*/
50
51
52
53     @Override
54     //Eclipse自动生成的hashCode重写
55     public int hashCode() {
56         final int prime = 31;
57         int result = 1;
58         result = prime * result + age;
59         result = prime * result + ((name == null) ? 0 : name.hashCode());
60         return result;
61     }
62
63
64     @Override
65     public boolean equals(Object obj) {
66         if (this == obj)
67             return true;
68         if (obj == null)
69             return false;
70         if (getClass() != obj.getClass())
71             return false;
72         Person other = (Person) obj;
73         if (age != other.age)
74             return false;
75         if (name == null) {
76             if (other.name != null)
77                 return false;
78         } else if (!name.equals(other.name))
79             return false;
80         return true;
81     }
82
83
84 }
时间: 2024-10-25 08:33:44

java为什么要重写hashCode方法和equals方法?的相关文章

Java 重写hashCode 方法和equals方法

package Container; import java.util.HashSet; import java.util.Iterator; /* Set 元素是无序的(存入和取出的顺序不一定一致),元素不可以重复 |---HashSet:底层数据结构是哈希表 | HashSet是如何保证元素唯一性呢? | 是通过两个方法来完成的 hashCode 和 equals来完成的 | 如果元素的hashCode值相同,才会判断 equals 是否为true | 如果hashCode值不相同,不会调用

集合类hashCode()方法和equals()方法

1.散列码: Object中的HashCode方法会返回该对象的的内存真实地址的整数化表示,这个形象的不是真正抵制的整数值就是哈希码. 2.利用哈希码向集合中插入数据的顺序? 向HashSet中添加对象时,HashSet先通过该对象的HashCode()计算出相应的桶,然后再根据equals()方法找到相应的对象,如果容器中已存在该对象则不再添加,如果不存在,则添加进去. 3.什么时候重写hashCode()方法?         String和Integer这些Java自带的类都重写了hash

java 数组的 toString 方法和 equals 方法以及 java.lang.Object 对象的 toString 方法和 equals 方法

1 public class Test { 2 public static void main(String[] args) { 3 int[] a = {1, 2, 4, 6}; 4 int[] b = a; 5 int[] c = {1, 2, 4, 6}; 6 7 //下面这个方法打印的是a数组的引用地址 8 System.out.println(a.toString()); 9 //下面这个方法比较的是两个数组的引用是否相等 10 System.out.println("a.equals

Java连载56-toSting方法和equals方法

Java连载56-toSting方法和equals方法一.关于object中的toString?方法: 1.SUN公司在Object类中设计toString方法的目的:返回java对象的字符串的表示形式. 2.在现实的开发过程中,Object里面的toString方法已经不够用了,因为Object的toString方法实现?的结果不满意.Object中的toString方法实现的结果不满意.Object中的呢toString?方法要被重写了. 3.println打印的如果是对象的话,那么就会默认

java课堂笔记------toString方法和equals方法

* 重写toString方法 * 当我们需要使用当前类的toString方法时,通常我们 * 就需要重写该方法.具体返回字符串的格式没有严格 * 要求,可根据将来实际开发中的需求而定.但通常反 * 回的字符串中应当包含当前类的属性值,以便了解当前 * 对象的信息. * 格式:(x,y) public String toString(){ return "(" + x + "," + y + ")"; } * 通常我们会重写一个类的equals方法

JAVA 面向对象补充[toString方法和equals方法]

一.toString  方法 这里的toString  和 C#的To string 是两回事. JAVA中to string : Object类中都有一个to string() 方法,创建的每一个类都会继承这个方法,返回一个对象的String 表示. 代码: 注释代码后结果: 取消注释后结果: 二.equals方法

Java Thread中,run方法和start方法的区别

 两种方法的区别: 1.start方法 用 start方法来启动线程,是真正实现了多线程, 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法.但要注意的是,此时无需等待run()方法执行完毕,即可继续执行下面的代码.所以run()方法并没有实现多线程. 2.run方法 run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是

JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别

关于获取类的字段有两种方式:getFields()和getDeclaredFields().我们先来看看这两者的区别吧: getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段. getDeclaredFields():获得某个类的所有声明的字段,即包括public.private和proteced,但是不包括父类的申明字段. 同样类似的还有getConstructors()和getDeclaredConstructors().getMethods()和getDe

java中paint方法和paintComponent方法的不同

/* 1.由Component.java源代码中可以看见其中的paint()方法体是空的,在Container中重写了该方法,其子类Window等也重写了该方法 2.由JComponent.java源代码中可以看见其中的paint()方法中调用paintComponent, paintChildren, paintBorder等方法: 所以该类中的paint方法会影响子组件的绘制, 而paintComponent方法只会影响该组件本身 3.paint方法 和 paintComponent方法都是