-
import
java.util.HashSet;
-
-
class
Dog{
-
String color;
-
-
public
Dog(String s){
-
color = s;
-
}
-
}
-
-
public
class
SetAndHashCode {
-
public
static
void
main(String[] args) {
-
HashSet<Dog> dogSet =
new
HashSet<Dog>();
-
dogSet.add(
new
Dog(
"white"
));
-
dogSet.add(
new
Dog(
"white"
));
-
-
System.out.println(
"We have "
+ dogSet.size() +
" white dogs!"
);
-
-
if
(dogSet.contains(
new
Dog(
"white"
))){
-
System.out.println(
"We have a white dog!"
);
-
}
else
{
-
System.out.println(
"No white dog!"
);
-
}
-
}
-
}
上述代码的输出为:
Set的contains(Object o) 方法详解
Java的API文档指出: 当且仅当 本set包含一个元素 e,并且满足(o==null ? e==null : o.equals(e))条件时,contains()方法才返回true. 因此 contains()方法 必定使用equals方法来检查是否相等.
需要注意的是: set 中是可以包含 null值的(常见的集合类都可以包含null值). 所以如果添加了null,然后判断是否包含null,将会返回true,代码如下所示:
-
HashSet<Dog> a =
new
HashSet<Dog>();
-
a.add(
null
);
-
if
(a.contains(
null
)){
-
System.out.println(
"true"
);
-
}
Java的根类Object定义了 public boolean equals(Object obj) 方法.因此所有的对象,包括数组(array,[]),都实现了此方法。
在自定义类里,如果没有明确地重写(override)此方法,那么就会使用Object类的默认实现.即只有两个对象(引用)指向同一块内存地址(即同一个实际对象, x==y为true)时,才会返回true。
如果把Dog类修改为如下代码,能实现我们的目标吗?
-
class
Dog{
-
String color;
-
-
public
Dog(String s){
-
color = s;
-
}
-
-
-
public
boolean
equals(Object obj) {
-
if
(!(obj
instanceof
Dog))
-
return
false
;
-
if
(obj ==
this
)
-
return
true
;
-
return
this
.color == ((Dog) obj).color;
-
}
-
-
}
英文答案是: no.
问题的关键在于
Java中hashCode与equals方法的紧密联系
. hashCode() 是Object类定义的另一个基础方法.
equals()与hashCode()方法之间的设计实现原则为:
如果两个对象相等(使用equals()方法),那么必须拥有相同的哈希码(使用hashCode()方法).
即使两个对象有相同的哈希值(hash code),他们不一定相等.意思就是: 多个不同的对象,可以返回同一个hash值.
hashCode()的默认实现是为不同的对象返回不同的整数.有一个设计原则是,hashCode对于同一个对象,不管内部怎么改变,应该都返回相同的整数值.
在上面的例子中,因为未定义自己的hashCode()实现,因此默认实现对两个对象返回两个不同的整数,这种情况破坏了约定原则。
-
class
Dog{
-
String color;
-
-
public
Dog(String s){
-
color = s;
-
}
-
-
-
public
boolean
equals(Object obj) {
-
if
(!(obj
instanceof
Dog))
-
return
false
;
-
if
(obj ==
this
)
-
return
true
;
-
return
this
.color == ((Dog) obj).color;
-
}
-
-
public
int
hashCode(){
-
return
color.length();
-
}
-
}
但是上面的hashCode实现,要求Dog的color是不变的.否则会出现如下的这种困惑:
-
import
java.util.HashSet;
-
import
java.util.Set;
-
-
-
public
class
TestContains {
-
-
-
public
static
final
class
Person{
-
private
String name =
""
;
-
public
Person(String n) {
-
setName(n);
-
}
-
public
String getName() {
-
return
name;
-
}
-
public
void
setName(String name) {
-
this
.name = (name==
null
)?
""
: name;
-
}
-
@Override
-
public
int
hashCode() {
-
-
return
name.length();
-
-
}
-
@Override
-
public
boolean
equals(Object obj) {
-
if
(!(obj
instanceof
Person)){
-
return
false
;
-
}
-
if
(obj ==
this
){
-
return
true
;
-
}
-
return
this
.name.equals(((Person)obj).name);
-
}
-
};
-
-
public
static
void
main(String[] args) {
-
Set<Person> persons =
new
HashSet<Person>();
-
-
Person person =
new
Person(
"tiemao"
);
-
persons.add(person);
-
-
person.setName(
"ren"
);
-
-
boolean
has = persons.contains(person);
-
int
size = persons.size();
-
System.out.println(
"has="
+has);
-
System.out.println(
"size="
+size);
-
}
-
}
参考文章:
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html
1.
Java equals() and hashCode() Contract
2.
HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
3.
Java: Find all callers of a method – get all methods that call a particular method
理解Java机制最受欢迎的8幅图
Java中Set的contains()方法 —— hashCode与equals方法的约定及重写原则翻译人员: 铁锚翻译时间: 2013年11月5日原文链接: Java hashCode() and equals() Contract for the contains(Object o) Method of Set本文主要讨论 集合Set 中存储对象的 hashCode
文章目录前言equals
方法
如何编写equals
方法
Object 类是
Java
中
所有类的始祖, 在
Java
中
每个类都是由它扩展而来的。如果一个类没有明确地指出其超类,Object 就被认为是这个类的超类(父类)。
equals
方法
在 Object 类
中
,equals
方法
将判断两个对象是否具有相同的引用。这与
Java
中
“==”的功能是一样的。换句话说,Object类
中
的equals
方法
并不会比较对象的内容(状态)。正因为如此,其他类往往需要重写equals
方法
比较对
1.重写equals1.1重写equals原因(1)Object类
中
equals
方法
比较的是两个对象的引用地址,只有对象的引用地址指向同一个地址时,才认为这两个地址是相等的,否则这两个对象就不想等。
(2)如果有两个对象,他们的属性是相同的,但是地址不同,这样使用equals()比较得出的结果是不相等的,而我们需要的是这两个对象相等,因此默认的equals()
方法
是不符合我们的要求的,这个时候我们就需要对equals()
方法
进行重写以满足我们的预期结果。
(3)在
java
的集合框架
中
需要用到equals()
因此Hash
Set
无序不可重复,也就意味着存放到Hash
Set
中
的对象元素是经过排序比较的。
如何比较呢?
1.HashMap底层是根据hashcode和equals来存放对象的。
2.我们知道Object父类
中
的hashcode
方法
默认返回的是对象的地址值,因此如果不重写hashcode,那么默认比较的是存放到集合
中
的对象
详解重写equals和hashcode为什么要重写equals( )怎样重写equals( )自反性原则对称性原则传递性原则为什么要重写hashcode( )怎样重写hashcode( )
为什么要重写equals( )
判断两个对象在逻辑上是否相等,如根据类的成员变量来判断两个类的实例是否相等,而继承Object
中
的equals
方法
只能判断两个引用变量是否是同一个对象,这样我们往往需要重写eq...
为什么重写equals时必须重写hashCode
方法
Java
中
的hash值主要是用来在散列存储结构
中
确定对象的存储地址的,提高对象的查询效率。
Java
设计的顶级父类Object类
中
,有两个
方法
很特殊,它们分别是equals
方法
与hashCode
方法
。——一旦重写了equals
方法
,就一定要重写hashCode
方法
。以下是Object的源码:
public class Object {
* Note that it is generally necessary to override th
hashcode
方法
会影响jvm性能?听上去天方夜谭,实际上蕴藏着一些微小的原理,接下来让我们走进hashcode
方法
,一探native
方法
源头。
默认实现是什么?
调用hashCode
方法
默认返回的值被称为identity hash code(标识哈希码),接下来我们会用标识哈希码来区分重写hashCode
方法
。如果一个类重写了hashCode
方法
,那么通过调用System.identityHashCode(Object o)
方法
获得标识哈希码。
在hashCode
方法
注释
中
,说hashCode一般是通过
关于hashCode和equals的处理,遵循如下规则:
1.只要重写equals
方法
,就必须要重写hashCode。
2.因为
Set
存储的是不重复的对象,依据hashCode和equals进行判断,所以
Set
存储的对象必须重写这两个
方法
。
3.如果自定义对象作为Map的键,那么必须重写hashCode和equals。
说明:String重写了hashCode和equals
方法
,所以我们可
hashCode和equals重写
重写hashCode和equals时需注意一点,equals相等则hashCode一定相等(相同对象hash值一致);hashCode相同equals不一定相等(hash值相同不能确定为同一个对象)。所以重写时要保证hashCode的字段和equals的字段相同,否则会导致相同对象有不同的hash值!
重写hashCode
Object
中
的hashCode为native
方法
,我们对类的hashCode重写本质上只是调用Object
中
的hashCode进行二次运算,不一定
如果两个对象相等,则 hashcode 一定也是相同的
两个对象相等,对两个对象分别调用 equals
方法
都返回 true
两个对象有相同的 hashcode 值,它们也不一定是相等的
因此,equals
方法
被覆盖过,则 hashCode
方法
也必须被覆盖
hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无...
equals()返利 https://m.cpa5.cn/
equals和hashcode
方法
我们都很了解,是Object类
中
的定义的
方法
,这意味着所有的类都隐式实现了这两个
方法
。
Object类
中
的equals
方法
的默认实现是比较.
哈希值一般用于一定的哈希结构存储
中
;
Java
中
hashCode
方法
是定义在Object类内的,也就是说,
java
中
的任何一个对象都有hashCode
方法
,可以获取当前对象的哈希值;
Object类内默认的哈希值是当前对象的空间首地址 十进制展示方式;
Java
中
规定如果两个
java
对象使
在覆盖的时候,必须要遵守它的通用约定。
自反性。对于任何非null的引用值x,x.equals(x)必须返回true
对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。
传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.
我们都知道,在
JAVA
世界
中
,万物皆对象。而equals和hashCode这两个
方法
也在Object类里被定义,先来看这两个
方法
在Object里面是如何实现的:
先看equals
方法
:
public boolean equals(Object obj) {
return (this == obj);
equals
方法
实现很简单,就是将某对象拿来和原始对象进行...