hashcode是什么意思_java中常常提起的hashCode到底是个啥?

493e769408a324982f7e32739d523f57.png

开始白活

其实这节本来是想聊聊集合的,

但是发现在聊集合之前,

有件事儿是绕不开的,

那就是hashcode编码

Hash我们都知道:

Hash是散列的意思,
就是把任意长度的输入,
通过散列算法变换成固定长度的输出,
该输出就是散列值。

那hashcode呢?

这货到底是个啥?


前情回顾

凑巧我们上文也讲到过,

正好趁此次我们来回顾一下,

就是在我们没有重写toString()方法时,

直接调用原始的toString()会给我们返回;

【对象的类名称 并 拼接一个16进制】

的hashcode码

(如下图示):

4e3689455ecb75fb9fecdc936896d64e.png

这个内地地址的16机制字符串到底是个什么呢?

我怀着一颗好奇的心,

举着一双欠揍的手,

进行了字符串的转换,

得到的结果

(如下图示):

997fc2092045f2e923104bc7c209b9eb.png

WHAT ???

特么这货是个啥?

2ebd7ad702460487728e6acad56f7155.png

怪我孤陋寡闻…

赶快转换成是10进制压压惊…

(如下图示):

049dd9cab116d4dde9bb256486c38752.png

顿时看着舒服多啦…

我们再次进入Object的toString()方法的源码,

(如下图示):

4e70e74f6c4a2c391a82493fe7dd6179.png

我们发现它是将

@后面hashCode()方法给toHexString()16进制加工了一下;

马上我们会想到,

如果直接调用hashCode()方法,

会得到什么呢?

我们打印一下看结果,

(如下图示):

d2c3f7ceda4e97a523a0d87ee8eb5e68.png

有同学发现啦,

这不是跟刚才我们在转换工具里得到的值一样吗?

来对照看一下,

(如下图示):

049dd9cab116d4dde9bb256486c38752.png

现在是不是脑子好像明白点什么了?

但 仔细一琢磨...

是不是又发现啥也没明白 [捂嘴笑…]


源码浅析

别着急,我们接着往下走,

咱们还是延续上文的套路,

将每种类型的hashcode()函数的源码都调出来,

然后逐一进行分解,

分别是Integer、String、person(Object对象)

先来看看Integer

(如下图示):

34efe61f8fb7a985f2cd99195667491c.png

Integer 包装类,

就是返回值本身

没什么可多说的。

再来看Object类,

(如下图示):

b5e7754c5543c265b388f0027fd1319e.png

咱们上文说过,

自定义的类都是继承自Object 类

我们看到Object类使用native关键字

说到native因为不是本篇的重心,
这里咱们只是简单扩展下,
让同学们知道这是啥咱们目的就达到啦,
当然有兴趣的同学可以自己查查资料,
深入了解一下;
在java源码中使用native关键字,
基本可以判断是调用了非java的代码接口,
例如java需要调用底层接口,
而底层实现的语言可能是使用C++、
或是使用C、或是使用VB等等开发的DLL动态库,
随用随调,避免重复造轮子。
我们都明白既然是非java的代码,
源码肯定是没有权限看到,
我们平时工作一样吗,
自己写了一个组件或者一个服务,
别人要想用,给他们开个口就可以了,
源码肯定不能开放给他们,
道理是一样的。

那么这里的大致意思:

就是Java通过Jvm告知操作系统(咱们现在使用的是Windows)底层

某某函数、某某方法…

我java现在需要用一下;

操作系统接到这个指令;

很通情达理的就给它返回相应结果…

最后是String

因为Object咱们看不到源码,

再耗下去也没意思,

快速pass到下环节,

下面是String 类源码,

(如下图示):

a070f6d76c6e9eb47a48f549cb84316d.png

这么一看String 类还是最有料的,

那么String的hashCode()函数到底说了个啥呢?

别着急…

我们下运行一下;

先看看结果;

(如下图示):

43e92d985cde8a6773f0656e11892a1f.png
第一个是Integer类型的根据我们刚刚看到的源码,
符合我们预期,的确是输出了它本身;

第三个Object 调用的是操作系统的hashcode,
返回的十进制数值。通过上文咱们的分析,
看不到源码,也讲不出个所以然。。。

我们现在来着重看看剩到最后的String类型

有同学可能有疑问;

明明我们给的字符串是的值是“a”

怎么返回个“97”呢?

同学们可能会想到,

咱们上文刚刚验证过,

已经知道:

hashcode使用的是10进制来表示的

“a”的10进制是不是“97”呢

我们查下ASCII码对照表

(如下图示):

5be171b0c873d670fad2a9ad97f8e6a1.png

据上图所示;

证明我们的猜测是正确的;

同学们注意啦:
字母大小写是敏感的,
大写和小写的十进制编码是不同的。

“a”的10进制就是用“97”来表示的;

为了更好进一步确认,

我们再换一个字符试一下;

(如下图示):

7b4f995151b63e4798673b7f5839e999.png

得出的结果:

[a 为 97 | b 为 98]

手动滚动上文的ASCII码对照表;

对比后;

再次证明是正确的;

完美贴合我们的预设。


卓见成效 ???

是不是发现很简单,

到这里是不是有点小激动,

hhhhhhhh….

稍安勿躁,

我们接着往下看:

这个时候我们将代码稍稍做下调整;

然后再来看一下,

(如下图示):

5bab835a0d9113aa6e03d1de115702f5.png

WHAT THE FU……(文明用语,人人有责,大家不要学博主)

你字符a输出的结果我懂,
你字符b输出的结果我也懂,
a和b这么在一块待着,
输出的这个货——我看不懂。

发生了什么?

输出的值怎么就变成了 “3105”了呢?

按照ASCII码的数值,不应该是“195(97+98)”吗?

那这个“3105”是怎么来的呢?


源码人力跟踪

别着急我们先分析以下源码(注意源码有注释)

如下:

 /**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
public int hashCode() {
        // 起到缓存的效果, 防止反复计算 hashCode
        int h = hash;  
        // 如果 h != 0, 说明已经计算过 hashCode 了, 直接返回缓存值即可
        if (h == 0 && value.length > 0) {
            char val[] = value;

            // 计算的核心步骤是这个 for 循环
            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
}

根据源码分析我们发现,

函数一进来;

就判断字符串(按照我们的例子就是[s])是否已经hash过(h!=0是否成立)啦,

就被缓存了,直接就返回啦,

如果没有,

就把字符串转换成字符(char[])数组,

进行循环计算;

因为咱们字符串的长度是2会循环两次

第一次循环后的结果是:
 h = 31 * h(默认值是0)+97(字符“a”的10进制表示)

也就是

 h = 31 * 0 +97 
 h = 97 (这符合我们只给字符“a”时返回的结果)
第二次循环的结果是:
 h = 31 * h(通过第一次循环,此时h已被赋值为“97”) +98(字符“b”的10进制表示)

也就是

 h =31 * 97 + 98 
 h = 3105 (正好是我们页面输出的值)

hashCode的作用

啰里啰嗦说了大半天,

hashcode的作用是什么?

想要明白hashCode的作用,

那咱们必须要先从Java中的集合说起...

那将又是个不小的话题;

我们决定放在下一篇,

到时仔细说道说道...

要不先给大家看着张截图,
虽然不具有什么代表性,
但也多少能让同学们有点启发;

(如下图示):

e2db79743d4c6580d5de4bde182c355d.png

看我画的箭头多好看,【一支穿云箭,千军万马来相见...】

hahahahahahahaha.....

再会...

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值