在Java中String数据类型的hashcode()是如何转化为十进制的

在Java中String数据类型,是如何转化为十进制的值的

话不多说直接上代码

    public static void main(String[] args) {
        String str1 = "通话";
        String str2 = "重地";
        String str3 = "你好";
        System.out.println("str1的hashcode是:"+str1.hashCode());
        System.out.println("str2的hashcode是:"+str2.hashCode());
        System.out.println("str3的hashcode是:"+str3.hashCode());
        System.out.println("a的hashcode是:"+"a".hashCode());
        System.out.println("A的hashcode是:"+"A".hashCode());
        System.out.println("Aa的hashcode是:"+"Aa".hashCode());
        System.out.println("哀悼的hashcode是:"+"哀悼".hashCode());
    }

输出结果

str1的hashcode是:1179395
str2的hashcode是:1179395
str3的hashcode是:652829
a的hashcode是:97
A的hashcode是:65
Aa的hashcode是:2112
哀悼的hashcode是:697340

这里的hashcode()的值是如何计算出来的呢?

我们先分析一下
a的hash值是97,A的hash值是65 。。。。。。这不就是ASCII编码对照的值么
ASCII编码对照表
那么问题来了,Aa的hashcode()值不应该是65+97=162么!为什么是2112呢?
还有,中文字符串的hashcode()是如何计算出来的?"通话"和"重地"的HashCode值为什么一样?

分析String的hashcode() 源码

String类的1465行


    private final char value[];

	private int hash;
	
 	public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

解析源码

Aa的hashcode()值不应该是65+97=162么!为什么是2112呢?

1.String a = “Aa”;实际就等于String a = new String("Aa);
2. 根据ASCII编码对照A=65,a=97
3.带入源码可知"Aa"被拆分成了数组char vaule[‘A’,‘a’];
4. 带入到hashcode源码逻辑可知:hash没有被赋值,所以这里hash变量的值为int的默认值:0
5."Aa"带入HashCode计算公式:31 * 65 + 97 = 2112

中文字符串的hashcode()是如何计算出来的?

1.String str1 = “通话”;实际就等于String str1 = new String("通话);
2.带入源码可知str1被拆分成了数组char vaule[‘通’,‘话’];
3.在Java中呢char是存储unicode编码的,unicode编码中有中文汉字,我们可以查询一下‘通’,‘话’分别在unicode中转化为10进制的值
4.‘通’,对应unicode编码的10进制值为:36890;‘话’对应unicode编码的10进制值为:35805;
5."通话"带入HashCode计算公式:31 * 36890 + 35805 = 1179395

 	public static void main(String[] args) {
        //unicode 编码总长度为:2^16
        for (int i = 0; i < 65536; i++){
            char str = (char) i;
            if (str == '通' | str == '话'){
                System.out.println(i+":"+str);
            }
            if (str == '重' | str == '地'){
                System.out.println(i+":"+str);
            }
        }
    }

输出结果

22320:35805:36890:37325:

为什么‘’通话’‘和‘’重地‘’hashcode一样?

根据上面的代码,可以计算出“通话”和“重地”分别对应的unicode编码为:

  • 通:36890
  • 话:35805
  • 重:37325
  • 地:22320

分别带入String对象的HashCode计算公式

  • 通话:
    31 * 36890 + 35805 = 1179395
  • 重地:
    31 * 37325 + 22320 = 1179395

结论

String字符串中的汉字,会被初始化为char数组,数组中存储的各个中文字符对应的unicode编码值;整个hashcode的运算是将数组中的元素(unicode编码值)逐个带入公式(h = 31 * h + val[i])运算得来。

分享一句我特别喜欢的话:每一天都是一个新的日子,走运当然是好的,不过我情愿做到分毫不差。这样,运气来的时候,你就有准备了。 ————海明威《老人与海》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值