2012-07-22 237 views
27

好了,在Java 7中,我们有Objects.hash()VS Objects.hashCode(),澄清需要

o.hashCode(); 
    Objects.hashCode(o); 

    Objects.hash(o); 

第2大致与零点检查相同,但什么是最后一个?

当提供单个对象引用时,返回的值确实不等于该对象引用的哈希码。

这是为什么?我的意思是,我们不需要3种方法来做同样的事情,我明白......但我们为什么需要Objects.hash()?你什么时候选择使用一个vs另一个?

回答

47

请参阅hashCodehash的文档。 hash需要Object...,而hashCode需要Object。给出的例子是:

@Override public int hashCode() { 
    return Objects.hash(x, y, z); 
} 
  • Objects.hash(Object... values)应在情况下,当你想要的对象序列,例如的散列使用当定义你自己的hashCode方法并且需要一个简单编码的散列值来组成你的对象的身份。
  • Objects.hashCode(Object o)应该在需要单个对象的散列时使用,如果对象为空则不会抛出。
  • Object::hashCode()应该在需要单个对象的散列时使用,并且如果对象为空则会引发异常。

请注意,hash(o)hashCode(o)不一定会返回相同的东西!如果你正在为一个对象做这件事,你应该使用hashCode

+0

在什么情况下'散列(o)'和'hashCode(o)'不会返回相同的值? ''hash()'state'的文档警告:当提供单个对象引用时,返回的值不等于该对象引用的哈希代码,但我仍在挖掘以找出原因。 – 2017-08-24 13:25:57

7

Object的默认hashCode()返回该对象的内存地址。所以,如果你有下面的类:

class Car { 
    String make; 
    String model; 
    int year; 

    public Car(String make, String model, int year) { 
     this.make = make; 
     this.model = model; 
     this.year = year; 
    } 
} 

再创建两个对象:

Car car1 = new Car("Toyota", "Corolla", 2010); 
Car car2 = new Car("Toyota", "Corolla", 2010); 

car1.hashCode()将从car2.hashCode()不同,因为每个对象都会有一个不同的内存地址。

如果您想让car1和car2返回相同的哈希码,该怎么办?在这种情况下,你应该覆盖默认的对象的hashCode()方法为汽车类,如下所示:

@Override 
public int hashCode() { 
    Object[] x = {model, make, Integer.valueOf(year)}; 
    int hashArray = Arrays.hashCode(x); 
    return hashArray; 
} 

这将使car1.hashCode()等于car2.hashCode(),因为String.hashCode()根据字符串内容计算hashCode,Integer.hashCode()将返回整数值本身。

在Java 7中,您可以使用Objects.hash(Object ... values)。因此,我们的新车hashCode()方法将如下所示:

@Override 
public int hashCode() { 
    return Objects.hash(model, make, year); 
} 

Objects.hash(对象...值)将调用Arrays.hashCode你。

最后,Objects.hashCode(Object o)将执行空检查。如果对象为null,它将返回0。否则,它会调用对象的hashCode()方法。

+0

大约20年来,默认的'hashCode()'没有返回内存地址。它不能真的。 GC移动物体。所谓的内存地址就是不可移动的句柄。 – EJP 2018-02-19 05:58:31

+0

基于Java文档https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode hashCode“通常通过将对象的内部地址转换为一个整数,但这种实现技术不是Java™编程语言所必需的。“ – ezzadeen 2018-02-25 00:39:01