您的位置:首页 > 移动开发 > Objective-C

Object类中的equals()与hashCode()

2018-02-07 22:31 134 查看

一、官方文档的描述

1. getClass()

public final native Class<?> getClass();


Class {@code Object} is the root of the class hierarchy.
Every class has {@code Object} as a superclass. All objects,
including arrays, implement the methods of this class.

Object类是类层次结构的根。每个类以Object类为父类。所有的对象,包括数组,都实现了这个类的方法。

#### 2. hashCode()

public native int hashCode();


Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by {@link java.util.HashMap}.

为该对象返回一个哈希码。这个方法支持哈希表的好处,比如java.util.HashMap提供的哈希表。

The general contract of {@code hashCode} is:

哈希表的一般要求是:

Whenever it is invoked on the same object more than once during
an execution of a Java application, the {@code hashCode} method
must consistently return the same integer, provided no information
used in {@code equals} comparisons on the object is modified.
This integer need not remain consistent from one execution of an
application to another execution of the same application.

无论何时,在执行一个Java程序时,对于同一个对象
hashCode
方法的多次调用,
hashCode
方法必须返回相同的值,前提是在比较两个对象时的信息没有变化。这个值不需要在程序切换执行期间保持一致。

If two objects are equal according to the {@code equals(Object)}
method, then calling the {@code hashCode} method on each of
the two objects must produce the same integer result.

如果根据
equals(Object)
方法两个对象相等,那么就在对这两个对象调用
hashCode
方法时产生的值将是相同的。

It is not required that if two objects are unequal according to the {@link java.lang.Object#equals(java.lang.Object)}
method, then calling the {@code hashCode} method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

如果根据
equals(Object)
方法两个对象不相等,并不要求对这两个对象调用
hashCode
方法时产生的值必须不同。然而,程序员应当知道,对不相等的对象产生不同的值可以提高哈希表的性能。

As much as is reasonably practical, the hashCode method defined by
class {@code Object} does return distinct integers for distinct
objects. (This is typically implemented by converting the internal
address of the object into an integer, but this implementation
technique is not required by the
Java™ programming language.)

为了尽可能的合理可行,hashCode方法被
Object
类定义为为不同的对象返回不同的整数值。(这通常通过将对象的内部地址转换为整数来实现,但是这种实现技术不是Java语言所要求的)

#### 3. equals()

Indicates whether some other object is “equal to” this one.

表明其他的对象是否与这个对象相等

The {@code equals} method implements an equivalence relation
on non-null object references:

equals
方法对非空对象的引用实现了等价关系

It is reflexive: for any non-null reference value
{@code x}, {@code x.equals(x)} should return
{@code true}.

自反性:对于任何非空的引用
x
x.equals(x)
都应返回
true


It is symmetric: for any non-null reference values
{@code x} and {@code y}, {@codex.equals(y)}
should return {@code true} if and only if
{@code y.equals(x)} returns {@code true}.

对称性:对于任何非空的引用
x
y
,当且仅当
y.equals(x)
返回
true
时,
x.equals(y)
应返回
true


It is transitive: for any non-null reference values
{@code x}, {@code y}, and {@code z}, if
{@codex.equals(y)} returns {@code true} and
{@code y.equals(z)} returns {@code true}, then
{@codex.equals(z)} should return {@code true}.

传递性:对于任何非空的引用
x
y
z
,如果
x.equals(y)
返回
true
并且
y.equals(z)
,那么
x.equals(z)
也返回
true


It is consistent: for any non-null reference values
{@code x} and {@code y}, multiple invocations of
{@codex.equals(y)} consistently return {@code true}
or consistently return {@code false}, provided no
information used in {@code equals} comparisons on the
objects is modified.

一致性:对于任何非空的引用
x
y
,多次连续调用
x.equals(y)
返回
true
,或连续返回
false
,对于已修改的对象,不提供
equals
得比较信息

For any non-null reference value {@code x},

{@code x.equals(null)} should return {@code false}.

对于任何非空的引用
x
x.equals(null)
返回
false


The {@code equals} method for class {@code Object} implements
the most discriminating possible equivalence relation on objects;
that is, for any non-null reference values {@code x} and
{@code y}, this method returns {@code true} if and only
if {@code x} and {@code y} refer to the same object
({@code x == y} has the value {@code true}).

Object
类的
equals
方法实现对象上最可能的等价关系;即,对于任何非空的引用
x
y
,这个方法当且仅当
x
y
都指向同一个对象
x == y
时返回
true


Note that it is generally necessary to override the {@code hashCode}
method whenever this method is overridden, so as to maintain the
general contract for the {@code hashCode} method, which states
that equal objects must have equal hash codes.

注意,当这个方法被覆盖时,通常必须重写
hashCode
方法,这是为了维持
hashCode
声明的规约:相等的对象必须拥有相同的哈希码

———

#### 二、思考

#### 1. 对于hashCode()方法

- 作用:产生哈希码

- 该方法有一条规约:
对同一个对象多次调用该方法,该方法必须返回相同的哈希码(前提是在比较时对象没有变化)。

#### 2. 对于equals()方法

- 作用:判断两个对象是否相等
- 四个性质(同时也是重写的原则):
1. **自反性**:
对于非空对象
x
,它与自己比较时,即
x.equals(x)
应返回
true

2. **对称性**:
对于非空对象
x
y
,当且仅当
y.equals(x)
返回
true
时,
x.equals(y)
返回
true

3. **传递性**:
就是如果非空对象x,y相等,y,z相等,则对象x,z相等
4. **一致性**:
对于非空对象
x
y
,只要该方法比较的对象没有改变,那么多次连续调用
x.equals(y)
都会返回相同的结果

- **注意**:

重写
equals()
后必须重写
hashCode()

这是为什么呢?
这是为了维持
hashCode
声明的规约:相等的对象必须拥有相同的哈希码
为什么要维持这个规约?
我们知道,在Java的Set类型的集合中,元素是无序的,所以Set中的元素不能重复。那么我们在放入元素的时候,Set是怎么知道我们放的元素是不是和里面已有的元素重复呢?也许我们会想到,他可能是一个个比较得来的,但是这样显然效率非常低,比如Set里面有成千上万个元素,直接遍历的话显然是效率低下的。所以就有人想出了哈希算法来提高在集合中查找的效率。

比如,我们来看HashMap中put的部分代码

public V put(K key, V value) {
// 计算当前key的hash值
return putVal(hash(key), key, value, false, true);
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// 通过(n - 1) & hash计算出索引,如果这个位置是空的,就直接放入
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
// 如果这个位置已经有key了
Node<K,V> e; K k;
// 判断这个key是不是已经存在
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
// 已经存在,则覆盖其value
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
......


我们可以看到,在put时,HashMap先通过hashCode()方法计算出hash值,然后根据hash值计算出索引位置,如果这个位置已经有元素了,这时才需要使用到equals()去判断当前要放的key和已有的key是不是相同,然后再做相应的处理。

可以看出,这样已经极大的减小了使用equals()的概率。

3. equals()和hashCode()的关系

如果x.equals(y)返回true,则说明两个对象相等,那么这两个对象的hashCode()返回的值也必须相等。

如果x.equals(y)返回false,则说明两个对象不相等,那么这两个对象的hashCode()返回的值可能相等,也可能不相等。对于这一点,我是这样理解的,因为hashCode()返回的是一个int类型的值,int型是32位、有符号的以二进制补码表示的整数,假设int型能表示n个数字,那么也就是说hashCode()能表示n个不同的元素,但是对象可能有n + 1个,那么这第n + 1个对象只能被之前那n个数字中的某一个表示,因此就出现了相同的hashCode值表示了两个不同的对象的情况,也就是对两个不同的对象调用hashCode()方法返回的值有可能不同。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jdk