# Java hashCode() 方法

**URL:** <https://www.isharkfly.com/t/java-hashcode/13447>\
**Category:** 程序语言\
**Tags:** java\
**Created:** [April 26, 2021, 7:44pm UTC](https://www.isharkfly.com/t/java-hashcode/13447 "2021-04-26T19:44:27Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![honeymoose](https://www.isharkfly.com/user_avatar/www.isharkfly.com/honeymoose/32/20796_2.png) [@honeymoose](https://www.isharkfly.com/u/honeymoose)\
**Post date:** [April 26, 2021, 7:44pm UTC](https://www.isharkfly.com/t/java-hashcode/13447/1 "2021-04-26T19:44:27Z")

</div>

在 java.lang.Object 类中有几个个非常重要的方法，我们今天来讨论下 hashCode() 这个方法。

## 什么是 Hash

Hash 中文叫做哈希也可以叫做散列，使用 Hash 的算法生成字符串或者数字的方法就可以称为 Hash 算法，或者散列算法。

如果还不太明白的话，考虑下 MD5。MD5 就是典型的哈希算法，通过 MD5 算法，不管你是输入字符串，图片，二进制文件，都能获得一个字符串。

获得这个字符串的算法就是 Hash 算法。

## 为什么要 Hash

我们在这里不打算讨论复杂的 Hash 算法或者 Hash 算法怎么去计算的。因为这样的话，你可能需要很长的时间才能搞明白到底怎么算出来的。

使用 Hash 算法的目的就是为了将获得的数据摘要信息尽量分散，并且尽量的不重复，同时还需要保证相同数据的 Hash 结果是相同不能变化的。

不管你将相同数据 Hash 多少遍，只要数据相同，那么 Hash 必须是相同的。

### 哈希碰撞

在现实生活中，不同数据的 Hash 结果可能是相同的。

考察下面的代码：

```auto
        logger.debug("HashCode AaAaAa - {}", "AaAaAa".hashCode());
        logger.debug("HashCode BBAaBB - {}", "BBAaBB".hashCode());

```

上面代码输出的结果是相同的，这种情况就是哈希碰撞（ Hash collision）。

![2021-04-26_15-40-24](https://www.isharkfly.com/images/transparent.png)

很遗憾，这种哈希碰撞在现实中是不能避免的。

![1280px-Hash_table_5_0_1_1_1_1_1_LL.svg](https://www.isharkfly.com/images/transparent.png)

## 常用的哈希算法

常用的 Hash 算法有下面的一些算法。

MD5 的算法已经不是安全的 Hash 算法了，在密码学和开发中，已经逐步推荐使用 SHA-256 算法了。

| 算法 | 输出长度（位） | 输出长度（字节） |
| --- | --- | --- |
| MD5 | 128 bits | 16 bytes |
| SHA-1 | 160 bits | 20 bytes |
| RipeMD-160 | 160 bits | 20 bytes |
| SHA-256 | 256 bits | 32 bytes |
| SHA-512 | 512 bits | 64 bytes |

根据碰撞概率，哈希算法的输出长度越长，就越难产生碰撞，也就越安全。

## Java 的 hashCode()

Java 中的 hashCode() 方法返回的数据类型是 int 类型。

下面以 String 对象的 hashCode 为例，官方解释中有关 String 对象 Hash 算法计算方式是：

```auto
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

```

针对输入字符串是不是 UTF16，将会有不同的计算方法。

 ![hash-01](https://com-ossez-www-discourse.s3.dualstack.us-east-2.amazonaws.com/discourse-uploads/original/2X/a/a4fa924f45b5b4e749dc8576b8ba701fddf83d78.png)

## IntelliJ IDEA 重写 Hash 算法

如果你不想使用 Java Object 对象中的 Hash 算法，你可以在你的对象中重写 Hash 算法。

在 IntelliJ IDEA 输入快捷键 Alt+Insert，这个将会弹出快速生成方法的选择项。

![hash-02](https://www.isharkfly.com/images/transparent.png)

随后将会提示你选用何种方法来创建 hashCode() 方法。你可以选择使用 JDK 自带的，你也可以选择使用 Apache Commons-lang 的方法来重写方法。当然，你也可以使用其他的一些方法来写，不管哪个方法来写，原理都是相通的。

![hash-03](https://www.isharkfly.com/images/transparent.png)

选择变量，在完成上面的方法选择后，将会提示你选择变量。

将需要创建的变量选择，然后下一步。

![hash-04](https://www.isharkfly.com/images/transparent.png)

同时还需要你选择非空的字段，你可以默认选择也可以不选择。

![hash-05](https://www.isharkfly.com/images/transparent.png)

如下，你可以看到使用 JDK 生成的默认的 hashCode 方法。

```auto
    @Override
    public int hashCode() {
        return Objects.hash(title, topic_id, raw, category, target_recipients, archetype, created_at);
    }

```

![hash-06](https://www.isharkfly.com/images/transparent.png)

如果你根据使用的是 Apache 的 Commons 生成的话，结果有所不同。

可以在 IDE 中自行研究下。

需要注意的是，在 hashCode 中，你可能会看到数字 17,31,37。

其实这些数字就是素数了，在 Java 面试的时候可能会有一道题目就是找出 100 以内的素数。

因为 Hash 算法在很多时候其实也可以用于密码学中，密码学的很多基础研究就是对素数的研究。

网络中广泛使用的RSA算法，就是基于素数性质的重要应用。

因此在 hashCode 的方法中，你能看到上面的数字，这个就是有关素数算法的实际应用之一。因为涉及到很多密码学的知识，我们这里就不实际展开了。

通过上面的说明，我们就能够在 Java 中对对象或者数据进行 Hash。

哈希算法和应用是 Java Hashmap 的基础，因此 hashCode 方法在 Java 中也会作为基础方法存在。
