您的位置:首页 > 编程语言 > Java开发

跟王老师学集合(九)Java中hashCode方法与equals方法的用法

2016-05-17 09:24 716 查看
Java中对象比较

主讲人:王少华 QQ群号:483773664

学习目标:

掌握java中的==、equals()、hashCode()的异同
一、问题
通过前面的学习,我们知道,Java集合有三个大的接口,List接口、Map接口、Set接口,这三个接口的特点是List接口中的元素能重复、Map接口中的key对象不能重复,Set接口中的元素是不可以重复的。那么问题来了,两个元素是否重复是根据什么来判断的。
二、Java中两个对象比较

(一)、==

1、Java中,比较简单类型变量用“==”,只要两个简单类型值相等即返回ture,否则返回false;
2、Java中,引用类型比较 ==,表示的是引用地址的比较。在用“==”比较引用类型时,仅当两个应用变量的对象指向同一个对象时,才返回ture。言外之意就是要求两个变量所指内存地址相等的时候,才能返回true,每个对象都有自己的一块内存,因此必须指向同一个对象才返回ture。
12345678910111213
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和==效果相同

1234
public
class
Person {
private
int
id;
private
String name;
}
12345678
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代码如下

12345678910111213
@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
;
}
12345678910
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内存地址。

12345678910
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、没有重写这二个方法

123456789101112131415161718192021
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;
}
}
1234567891011121314
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、重写这二个方法
123456789101112131415161718
@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
;
}
1234567891011121314
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

来自为知笔记(Wiz)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java equals 学习目标