在 Java 中使用 hashCode 有什么用?

在 Java 中,obj.hashCode()返回一些值。这个散列码在编程中有什么用?

190687 次浏览

来自 贾瓦多克:

返回对象的哈希代码值。这种方法受益于哈希表,例如 java.util.Hashtable提供的哈希表。

hashCode的总合同是:

  • 只要在 Java 应用程序的执行过程中对同一对象多次调用它,hashCode方法就必须始终返回 相同的整数,前提是不修改对象的等于比较中使用的任何信息。从应用程序的一次执行到同一应用程序的另一次执行,这个整数不需要保持一致。

  • 如果根据 equals(Object)方法,两个对象是相等的,那么对每个对象调用 hashCode方法必须产生相同的整数结果。

  • 没有要求,如果根据 equals(java.lang.Object)方法,两个对象是不相等的,那么对每个对象调用 hashCode方法必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

由 Object 类定义的 hashCode 方法为不同的对象返回不同的整数。(这通常由 将对象的内部地址转换为整数实现,但 Java 编程语言不需要这种实现技术。)

虽然散列码与您的业务逻辑没有任何关系,但是在大多数情况下我们必须处理它。因为当您的对象放入一个基于散列的容器(HashSetHashMap...)时,容器将放入/获取元素的散列码。

hashCode()Hash实现(如 HashMapHashTableHashSet等)中用于 水桶

hashCode()接收到的值用作存储 set/map 元素的 桶号。这个 bucket 编号是 set/map 中元素的 地址

当您执行 contains()时,它将获取元素的 hash 代码,然后寻找 hash 代码指向的 bucket。如果在同一个 bucket 中发现多于1个元素(多个对象可以有相同的哈希代码) ,那么它使用 equals()方法来计算对象是否相等,然后决定 contains()是真还是假,或者决定元素是否可以添加到集合中。

hashCode()是一个接受对象并输出数值的函数。如果对象没有改变,那么对象的散列码总是相同的。

HashMapHashTableHashSet等需要存储对象的函数将使用内部数组大小的 hashCode模块来选择存储对象的“内存位置”(即数组位置)。

在某些情况下可能会发生冲突(两个对象最终得到相同的散列码) ,当然,这需要仔细解决。

hashCode()是由 JVM 为每个对象创建生成的 独一无二代码。

我们使用 hashCode()对哈希表、哈希映射等相关算法进行一些操作。

hashCode()的优点使得搜索操作变得容易,因为当我们搜索一个具有唯一代码的对象时,它有助于找到那个对象。

但是我们不能说 hashCode()是一个对象的地址。它是 JVM 为每个对象生成的唯一代码。

这就是为什么现在哈希算法是最流行的搜索算法。

hashCode()返回的值是对象的哈希代码,它是以十六进制表示的对象的内存地址。

根据定义,如果两个对象相等,则它们的哈希代码也必须相等。如果重写 equals()方法,则会更改两个对象相等的方式,并且 Object 对 hashCode()的实现不再有效。因此,如果重写 equals ()方法,也必须重写 hashCode()方法。

这个答案来自 JavaSE8官方教程文档

HashCode ()的一个用法是 建立捕捉机制。 看看这个例子:

        class Point
{
public int x, y;


public Point(int x, int y)
{
this.x = x;
this.y = y;
}


@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;


Point point = (Point) o;


if (x != point.x) return false;
return y == point.y;
}


@Override
public int hashCode()
{
int result = x;
result = 31 * result + y;
return result;
}


class Line
{
public Point start, end;


public Line(Point start, Point end)
{
this.start = start;
this.end = end;
}


@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;


Line line = (Line) o;


if (!start.equals(line.start)) return false;
return end.equals(line.end);
}


@Override
public int hashCode()
{
int result = start.hashCode();
result = 31 * result + end.hashCode();
return result;
}
}
class LineToPointAdapter implements Iterable<Point>
{
private static int count = 0;
private static Map<Integer, List<Point>> cache = new HashMap<>();
private int hash;


public LineToPointAdapter(Line line)
{
hash = line.hashCode();
if (cache.get(hash) != null) return; // we already have it


System.out.println(
String.format("%d: Generating points for line [%d,%d]-[%d,%d] (no caching)",
++count, line.start.x, line.start.y, line.end.x, line.end.y));
}

散列码是从任何对象生成的数字。

这样就可以在 Hashtable 中快速存储/检索对象。

设想下面这个简单的 例子:

在你面前的桌子上。你有九个盒子,每个盒子上都标着1到9的数字。这些盒子里还有一大堆各种各样的东西可以存放,但是一旦它们被放进去了,你就需要尽快找到它们。

你需要的是一种方法,即时决定你把每个对象的盒子。就像索引一样。你决定找到卷心菜,所以你查了卷心菜在哪个盒子里,然后直接去那个盒子拿。

现在假设您不想为索引操心,而是希望能够立即从对象中找到它所在的框。

在这个例子中,让我们使用一个非常简单的方法来做到这一点-对象名称中的字母数。卷心菜放在第七个盒子里豌豆放在第三个盒子里火箭放在第六个盒子里班卓琴放在第五个盒子里,以此类推。

那犀牛呢?它有10个字符,所以我们稍微改变一下算法,然后“环绕”,这样10个字母的对象放在第1个框中,11个字母放在第2个框中,以此类推。应该能盖住任何东西。

有时候一个盒子里会有不止一个物体,但是如果你在找一个火箭,比较一个花生和一个火箭,比检查一整堆卷心菜,豌豆,班卓琴和犀牛要快得多。

那是散列码。一种从对象获取数字的方法,这样它就可以存储在 Hashtable 中。在 Java 中,哈希代码可以是任何整数,每个对象类型负责生成自己的哈希代码。查找 Object 的“ hashCode”方法。

资料来源 -给你