简体   繁体   English

何时使用System.identityhashcode()和hashcode()方法?

[英]When to use System.identityhashcode() and hashcode() method?

何时使用System.identityhashcode()和hashcode()方法?*

According to the javadoc, the System.identityHashCode(Object o) : 根据javadoc, System.identityHashCode(Object o)

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). 返回给定对象的相同哈希码,就像默认方法hashCode()返回的一样,无论给定对象的类是否覆盖hashCode()。 The hash code for the null reference is zero. 空引用的哈希码为零。

So, at the first place, System.identityHashCode(nullReference) will always give you 0 , instead of nullReference.hashCode() which will obviously give you a NullPointerException at Runtime. 所以,首先, System.identityHashCode(nullReference)将总是给你0 ,而不是nullReference.hashCode() ,这显然会在运行时给你一个NullPointerException

Let's, however, consider the following class: 但是,让我们考虑以下课程:

public class MysteriousOne {
    @Override
    public int hashCode() {
        return 0xAAAABBBB;
    }

    //override equals() and so on...
}

The class overrides hashCode() , which is perfectly fine, even though the hash code for every instance would be the same, which however is not fine, if you want to distinguish identities of several instances. 该类重写了hashCode() ,这是完全正常的,即使每个实例的哈希码都是相同的,但是如果你想要区分几个实例的身份,那么这个哈希码就不行了。 Usually, you'd try the output of the .toString() method (which by default gives the classname, followed by a @ followed by the hashCode() output), for example, to find out the real identity of an object, but is in this case the output would be the same: 通常,你会尝试输出.toString()方法(默认情况下给出类名,然后是@后跟hashCode()输出),例如,找出对象的真实身份,但是在这种情况下,输出将是相同的:

MysteriousOne first = new MysteriousOne();
MysteriousOne second = new MysteriousOne();
System.out.println("First: " + first);
System.out.println("Second: " + second);

The output would be: 输出将是:

First: MysteriousOne@aaaabbbb
Second: MysteriousOne@aaaabbbb

So, having such implementation of hashCode() is impossible to distinguish between identities of several instances. 因此,拥有hashCode()这种实现是不可能区分几个实例的身份。 Which is where System.identityHashCode() is being handy. 这就是System.identityHashCode()的用武之地。

If you do 如果你这样做

System.out.println("First: " + System.identityHashCode(first));
System.out.println("Second: " + System.identityHashCode(second));

you'd get two different numbers for the different instances, even though the hashCode() of their class implementation returns a constant (actually here the overridden implementation of hashCode() will not be called at all, as per javadoc): 你会为不同的实例得到两个不同的数字,即使它们的类实现的hashCode()返回一个常量(实际上这里根本不会调用hashCode()的重写实现,如javadoc所示):

First: 366712642
Second: 1829164700

Further, you can even pass primitives to System.identityHashCode(Object o) , as they will be boxed to their corresponding wrappers: 此外,您甚至可以System.identityHashCode(Object o)语传递给System.identityHashCode(Object o) ,因为它们将被装箱到相应的包装器:

int i = 5;
System.out.println(System.identityHashCode(i));

More info: 更多信息:

Some of your classes may override hashcode() method in your system. 您的某些类可能会覆盖系统中的hashcode()方法。 For those objects, this method provides the hash code of the provided Object as would be returned from its ultimate parent java.lang.Object . 对于这些对象,此方法提供从其最终父java.lang.Object返回的提供的Object的哈希码。 Refer Java API to see the description from language designers. 请参阅Java API以查看语言设计者的说明。

I believe the use is when you want to create almost non-unique objects for some reasons. 我相信当你想要出于某些原因创建几乎非唯一的对象时。 When I say almost, there may be objects with same hash code. 当我说差不多时,可能存在具有相同哈希码的对象。 You would actually minimize the use of equals methods in doing so. 实际上,您最大限度地减少了equals方法的使用。

From the documentation : 文档

public static int identityHashCode(Object x) public static int identityHashCode(Object x)

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). 返回给定对象的相同哈希码,就像默认方法hashCode()返回的一样,无论给定对象的类是否覆盖hashCode()。 The hash code for the null reference is zero. 空引用的哈希码为零。

Note that identityHashCode returns the hashCode as implemented in the Object class and that's not what you usually want, so you should just use yourObject.hashCode() . 请注意, identityHashCode返回在Object类中实现的hashCode ,这不是您通常想要的,因此您应该只使用yourObject.hashCode()

Regarding if there could be some use cases for this method, if you have an array of Objects you are iterating through that could have some null in it, and you need the hashCode of those Objects, using System.identityHashCode(obj) could save you one null check, not that big of an improvement. 关于是否可能有这个方法的一些用例,如果你有一个Objects数组,你正在迭代它可能有一些null ,你需要这些对象的hashCode ,使用System.identityHashCode(obj)可以节省你一个空检查,没有那么大的改进。

The System.identityhashcode() always return the default java.lang.Object implementation, even if the class for a particular object overrides this and computes a different hash code. System.identityhashcode()始终返回默认的java.lang.Object实现,即使特定对象的类会覆盖它并计算不同的哈希代码。

Under some circumstance, you may need this kind of definition: Two objects o1 and o2 are considered equal if and only if o1 == o2. 在某些情况下,您可能需要这种定义:当且仅当o1 == o2时,两个对象o1和o2被认为是相等的。 In normal implementations, two objects o1 and o2 are considered equal if and only if o1 == null ? 在正常实现中,当且仅当o1 == null时,两个对象o1和o2被认为是相等的? o2 == null : o1.equals(o2). o2 == null:o1.equals(o2)。 If two objects are equal if and only if o1 == o2, they must have the same hashcode. 如果且当且仅当o1 == o2时两个对象相等,则它们必须具有相同的哈希码。 So you should use System.identityhashcode(). 所以你应该使用System.identityhashcode()。

Here are some code snippets I came across. 以下是我遇到的一些代码片段。


private static int hash(Object x, int length) {
    int h = System.identityHashCode(x);
    // Multiply by -127, and left-shift to use least bit as part of hash
    return ((h << 1) - (h << 8)) & (length - 1);
}

IdentityHashMap.java IdentityHashMap.java

public int hashCode() {
    return System.identityHashCode(instance);
}

@Override
@SuppressWarnings("rawtypes")
public boolean equals(final Object other) {
    return other instanceof IdentityWrapper &&
         ((IdentityWrapper) other).instance == instance;
}

IdentityWrapper.java (From Apache Commons Pool 2) IdentityWrapper.java (来自Apache Commons Pool 2)

Well, for starters, while System of course has a hashCode() method (every Object has one), I don't see much reason in calling it. 好吧,对于初学者来说,虽然System当然有一个hashCode()方法(每个Object都有一个),但是我没有太多理由去调用它。 Or any chance of even getting a System object to call it on, as System is final and the constructor is private . 或者甚至有机会获得一个System对象来调用它,因为System是final并且构造函数是private So, probably "pretty much never" for hashCode() , I guess. 所以,对于hashCode() ,可能“几乎从不”,我想。

So, that leaves us with System.identityHashCode(Object) which gives your simply the default hashcode value for any Object. 因此,我们使用了System.identityHashCode(Object) ,它为您提供了任何Object的默认哈希码值。 So, in other words, you don't need it very often, because if you don't override the hashCode() method in your class, you will already get the same return value by default for your Objects (because effectively the default hashCode(), when you have not overriden the hashCode() method, is simply System.identityHashCode(this) ). 所以,换句话说,你不经常需要它,因为如果你没有覆盖你的类中的hashCode()方法,你的对象默认会得到相同的返回值(因为实际上是默认的hashCode) (),当你没有覆盖hashCode()方法时,只是System.identityHashCode(this) )。 There might be some use cases when to use it, but they are pretty rare. 可能有一些用例何时使用它,但它们非常罕见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM