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

时间:2015-07-23 06:27:31

标签: java hashcode

  

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

5 个答案:

答案 0 :(得分:2)

根据javadoc,System.identityHashCode(Object o)

  

返回与默认方法hashCode()返回的给定对象相同的哈希码,无论给定对象的类是否覆盖hashCode()。空引用的哈希码为零。

因此,首先,System.identityHashCode(nullReference)将始终为您提供0,而不是nullReference.hashCode(),这显然会在运行时为您提供NullPointerException

但是,请考虑以下课程:

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

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

该类覆盖hashCode(),这是完全正常的,即使每个实例的哈希码都是相同的,但是如果你想要区分几个实例的身份,那么这样就不行了。通常,您可以尝试.toString()方法的输出(默认情况下会提供类名,后跟@后跟hashCode()输出),例如,查找输出对象的真实身份,但在这种情况下,输出将是相同的:

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

输出结果为:

First: MysteriousOne@aaaabbbb
Second: MysteriousOne@aaaabbbb

因此,拥有hashCode()的这种实现是不可能区分几个实例的身份。这是System.identityHashCode()方便的地方。

如果你这样做

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

你为不同的实例得到两个不同的数字,即使它们的类实现的hashCode()返回一个常量(实际上在这里,hashCode()的重写实现根本不会被调用,根据javadoc):

First: 366712642
Second: 1829164700

此外,您甚至可以将原语传递给System.identityHashCode(Object o),因为它们将被装箱到相应的包装器中:

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

更多信息:

答案 1 :(得分:0)

您的某些课程可能会覆盖系统中的hashcode()方法。对于这些对象,此方法提供从其最终父java.lang.Object返回的提供的Object的哈希码。请参阅Java API以查看语言设计人员的说明。

我相信当你想要出于某些原因创建几乎非唯一的对象时。当我说差不多时,可能存在具有相同哈希码的对象。实际上,您最少会使用equals方法。

答案 2 :(得分:0)

来自documentation

  

public static int identityHashCode(Object x)

     

返回与默认方法hashCode()返回的给定对象相同的哈希码,无论给定对象的类是否覆盖hashCode()。空引用的哈希码为零。

请注意,identityHashCode会返回hashCode类中实现的Object,而这不是您通常想要的,因此您应该只使用yourObject.hashCode()

关于此方法是否可能存在某些用例,如果您有一个Objects数组,您正在迭代它可能会有一些null,并且您需要hashCode使用System.identityHashCode(obj)这些对象可以为您节省一次空检查,而不是那么大的改进。

答案 3 :(得分:0)

System.identityhashcode()总是返回默认的java.lang.Object实现,即使特定对象的类覆盖了它并计算不同的哈希代码。

在某些情况下,您可能需要这种定义:当且仅当o1 == o2时,两个对象o1和o2被认为是相等的。在正常实现中,当且仅当o1 == null时,两个对象o1和o2被认为是相等的? o2 == null:o1.equals(o2)。 当且仅当o1 == o2时,两个对象相等,它们必须具有相同的哈希码。所以你应该使用System.identityhashcode()。

以下是我遇到的一些代码段。

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

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 (来自Apache Commons Pool 2)

答案 4 :(得分:-1)

嗯,对于初学者来说,虽然System当然有一个hashCode()方法(每个Object都有一个),但我没有太多理由在调用它。或者甚至有机会获得一个System对象来调用它,因为System为final且构造函数为private。所以,对于hashCode(),可能“几乎从不”,我猜。

所以,这给我们留下了System.identityHashCode(Object),它为您提供了任何Object的默认哈希码值。所以,换句话说,你不经常需要它,因为如果你没有覆盖你的类中的hashCode()方法,你的对象默认会得到相同的返回值(因为实际上是默认的hashCode) (),当你没有覆盖hashCode()方法时,只是System.identityHashCode(this))。可能有一些使用案例何时使用,但它们非常罕见。