跟王老师学集合Java中hashCode方法与equals方法的用法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跟王老师学集合Java中hashCode方法与equals方法的用法相关的知识,希望对你有一定的参考价值。
Java中对象比较
主讲人:王少华 QQ群号:483773664
学习目标:
掌握java中的==、equals()、hashCode()的异同
一、问题
通过前面的学习,我们知道,Java集合有三个大的接口,List接口、Map接口、Set接口,这三个接口的特点是List接口中的元素能重复、Map接口中的key对象不能重复,Set接口中的元素是不可以重复的。那么问题来了,两个元素是否重复是根据什么来判断的。
二、Java中两个对象比较(一)、==
1、Java中,比较简单类型变量用“==”,只要两个简单类型值相等即返回ture,否则返回false;
2、Java中,引用类型比较 ==,表示的是引用地址的比较。在用“==”比较引用类型时,仅当两个应用变量的对象指向同一个对象时,才返回ture。言外之意就是要求两个变量所指内存地址相等的时候,才能返回true,每个对象都有自己的一块内存,因此必须指向同一个对象才返回ture。
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class TestDengHao { public static void main(String[] args) { int a = 12 ; int b = 12 ; System.out.println(a==b); Integer aA = 12 ; Integer bB = 12 ; System.out.println(aA==bB); Integer A = new Integer( 12 ); Integer B = new Integer( 12 ); System.out.println(A==B); } } |
上述代码运行结果是
A和B是两个不同的对象(尽管某个成员的值相等),所以结果是false。
(二) equals
1、equals()方法来自于Object类,每个自定义的类都可以重写这个方法。Object类中的equals()方法仅仅通过“==”来比较两个对象是否相等,即默认情况下,equals和==效果相同
1 2 3 4 | public class Person { private int id; private String name; } |
1 2 3 4 5 6 7 8 | public class TestEquals { public static void main(String[] args) { Person p1 = new Person(); Person p2 = new Person(); System.out.println( "==:" +(p1==p2)); System.out.println( "equals:" +p1.equals(p2)); } } |
上述代码运行效果
(三)、重写equals
如果需求要求,只要是id相同的,表示的是同一个人。为了实现这个需求,我们需要重写equals方法,重写的一般规则如下
1、先用“==”判断是否相等。
2、判断equals()方法的参数是否为null,
如果为null,则返回false;因为当前对象不可能为null,如果为null,则不能调用其equals()方法,否则抛java.lang.NullPointerException异常。
当参数不为null,则如果两个对象的运行时类(通过getClass()获取)不相等,返回false,否则继续判断。
3、判断类的成员是否对应相等。
本需求只要求比较id,所以重写equals代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Override public boolean equals(Object obj) { if ( this == obj) return true ; if (obj == null ) return false ; if (getClass() != obj.getClass()) return false ; Person other = (Person) obj; if (id != other.id) return false ; return true ; } |
1 2 3 4 5 6 7 8 9 10 | public class TestEquals { public static void main(String[] args) { Person p1 = new Person(); p1.setId( 1 ); Person p2 = new Person(); p2.setId( 1 ); System.out.println( "==:" +(p1==p2)); System.out.println( "equals:" +p1.equals(p2)); } } |
上述代码运行效果
(四)、hashcode()
hashCode是根类Obeject中的方法,是一个本地方法,它的实现是根据本地机器相关的。默认情况下,Object中的hashCode() 返回对象的32位jvm内存地址。也就是说如果对象不重写该方法,则返回相应对象的32为JVM内存地址。
1 2 3 4 5 6 7 8 9 10 | public class TestEquals { public static void main(String[] args) { Person p1 = new Person(); p1.setId( 1 ); Person p2 = new Person(); p2.setId( 1 ); System.out.println( "p1.hashCode:" +p1.hashCode()); System.out.println( "p2.hashCode:" +p2.hashCode()); } } |
(五)、类中的equals和hashCode
1、Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的
2、结论:equals()相等的两个对象,hashcode()一定相等,equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。
3、理解:equals相等,说明内存地址是一样,那么hashCode肯定一样;
eqauls不相等,说明内存地址是不一样的,又因为hashCode是机器生成的,有可能在生成的时候产生冲突造成的。
三、在java的集合中(一)判断两个对象是否相等的规则
Java系统首先调用对象的hashCode()方法获得该对象的哈希码表,然后根据哈希吗找到相应的存储区域,最后取得该存储区域内的每个元素与该对象进行equals方法比较。
具体规则如下:
1,判断两个对象的hashCode是否相等
如果不相等,认为两个对象也不相等,完毕
如果相等,转入2
2),判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等。
为什么是两条准则,难道用第一条不行吗?不行,因为前面已经说了,hashcode()相等时,equals()方法也可能不等,所以必须用第2条准则进行限制,才能保证加入的为非重复元素。
(二)应用hashCode和equals
1、没有重写这二个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class Person { private int id; private String name; public Person(){} public Person( int id, String name) { this .id = id; this .name = name; } public int getId() { return id; } public void setId( int id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class TestHashSet { public static void main(String[] args) { HashSet hs = new HashSet(); hs.add( new Person( 1 , "zhangsan" )); hs.add( new Person( 2 , "lisi" )); hs.add( new Person( 3 , "wangwu" )); hs.add( new Person( 1 , "zhangsan" )); Iterator it = hs.iterator(); while (it.hasNext()) { Person person = (Person) it.next(); System.out.println(person.getId()+ ":" +person.getName()); } } } |
运行结果
分析:因为在根据hashcode()对两次建立的new Student(1,"zhangsan")对象进行比较时,生成的是不同的哈希码值,所以hashset把他当作不同的对象对待了,当然此时的equals()方法返回的值也不等。
2、重写这二个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Override public int hashCode() { // TODO Auto-generated method stub return id*name.hashCode(); } @Override public boolean equals(Object obj) { if ( this == obj) return true ; if (obj == null ) return false ; if (getClass() != obj.getClass()) return false ; Person other = (Person) obj; if (id != other.id) return false ; return true ; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class TestHashSet { public static void main(String[] args) { HashSet hs = new HashSet(); hs.add( new Person( 1 , "zhangsan" )); hs.add( new Person( 2 , "lisi" )); hs.add( new Person( 3 , "wangwu" )); hs.add( new Person( 1 , "zhangsan" )); Iterator it = hs.iterator(); while (it.hasNext()) { Person person = (Person) it.next(); System.out.println(person.getId()+ ":" +person.getName()); } } } |
上述代码运行效果
可以看到重复元素的问题已经消除。
四、总结
1、默认。
==默认比较对象在JVM中的地址。
hashCode 默认返回对象在JVM中的存储地址。
equal比较对象,默认也是比较对象在JVM中的地址,同==
2、当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
3、Java对象比较,一般情况下都要重写hashCode和equals二个方法
五、视频地址
http://edu.51cto.com/course/course_id-6028.html
以上是关于跟王老师学集合Java中hashCode方法与equals方法的用法的主要内容,如果未能解决你的问题,请参考以下文章