关于hashcode 里面 使用31 系数的问题

首先我们来了解一下hashcode,什么是hashcode?有什么作用?

hashcode其实就是散列码,使用hashcode使用高效率的哈希算法来定位查找对象!

我们在使用容器来存储数据的时候会计算一串散列码,然后将数据放入容器。

如:String s =“java”,那么计算机会先计算散列码,然后放入相应的数组中,数组的索引就是从散列吗计算来的,然后再装入数组里的容器里,如List.这就相当于把你要存的数据分成了几个大的部分,然后每个部分存了很多值, 你查询的时候先查大的部分,再在大的部分里面查小的,这样就比先行查询要快很多!

一个对象的HashCode就是一个简单的Hash算法的实现,虽然它和那些真正的复杂的!Hash算法相比还不能叫真正的算法,但如何实现它,不仅仅是程序员的编程水平问题, 而是关系到你的对象在存取时性能的非常重要的问题.有可能,不同HashCode可能 会使你的对象存取产生成百上千倍的性能差别!

java String在打印这个类型的实例对象的时候总是显示为下面的形式

test.Test$tt@c17164

上面test.Test是类名$tt是我自己写的内部类,而@后面这一段是什么呢?他其实就是tt这个实例类的hashcode是的16进制!

它使用了Object 里面的toString()方法

Java代码

  1. return getClass().getName() + “@” + Integer.toHexString(hashCode()); 

继续看看java里 String hashcode的源码:

Java代码

public int hashCode() {

int h = hash;
int len = count;
if (h == 0 && len > 0) {
int off = offset;
char val[] = value;

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


其实上面的实现也就是数学里:

Java代码

s[0]31^(n-1) + s[1]31^(n-2) + … + s[n-1] 

的实现!我们会注意那个狗血的31这个系数为什么总是在里面乘来乘去?为什么不适用32或者其他数字?

大家都知道,计算机的乘法涉及到移位计算。当一个数乘以2时,就直接拿该数左移一位即可!选择31原因是因为31是一个素数!

所谓素数:

质数又称素数
。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。

素数在使用的时候有一个作用就是如果我用一个数字来乘以这个素数,那么最终的出来的结果只能被素数本身和被乘数还有1来整除!如:我们选择素数3来做系数,那么3*n只能被3和n或者1来整除,我们可以很容易的通过3n来计算出这个n来。这应该也是一个原因!

在存储数据计算hash地址的时候,我们希望尽量减少有同样的hash地址,所谓“冲突”。如果使用相同hash地址的数据过多,那么这些数据所组成的
hash链就更长,从而降低了查询效率!所以在选择系数的时候要选择尽量长的系数并且让乘法尽量不要溢出的系数,因为如果计算出来的hash地址越大,所
谓的“冲突”就越少,查找起来效率也会提高。

31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化,使用31的原因可能是为了更好的分配hash地址,并且31只占用5bits!

在java乘法中如果数字相乘过大会导致溢出的问题,从而导致数据的丢失.

而31则是素数(质数)而且不是很长的数字,最终它被选择为相乘的系数的原因不过与此!

参考文档:http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/

http://www.cogs.susx.ac.uk/courses/dats/notes/html/node114.html

本文来源于"阿里中间件团队播客",原文发表时间" 2012-03-19"

时间: 2024-05-20 18:23:02

关于hashcode 里面 使用31 系数的问题的相关文章

重写hashCode()和equals()方法

hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们就讨论一下如何正解理解和使用这2个方法. 如何重写equals方法 如何重写hashCode方法 重写equals而不重写hashCode的风险 如何重写equals()方法 如果你决定要重写equals()方法,那么你一定要明确这么做所带来的风险,并确保自己能写出一个健壮的equals()方法.一定要注意的一点是,在重写equals()后,一定要重写has

Java 理论与实践: 哈希

每个Java对象都有hashCode()和 equals()方法.许多类忽略(Override)这些方法的缺省实施,以在对象实例之间提供更深层次的语义可比性.在Java理念和实践这一部分,Java开发人员Brian Goetz向您介绍在创建Java类以有效和准确定义hashCode()和equals()时应遵循的规则和指南.您可以在讨论论坛与作者和其它读者一同探讨您对本文的看法.(您还可以点击本文顶部或底部的讨论进入论坛.) 虽然Java语言不直接支持关联数组 -- 可以使用任何对象作为一个索引

怎样通过Parcelable来传递Collection

原文:http://www.oschina.net/code/explore/android-4.0.1/core/java/android/net/LinkProperties.java /** * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this fi

使用IntelliJ IDEA开发SpringMVC网站(三)数据库配置

原文:使用IntelliJ IDEA开发SpringMVC网站(三)数据库配置 摘要 讲解在IntelliJ IDEA中,如何进行Mysql数据库的配置 目录[-] 文章已针对IDEA 15做了一定的更新,部分更新较为重要,请重新阅读文章并下载最新源码. 六.数据库配置 1.创建Mysql数据库 2.IntelliJ IDEA导入数据库 3.配置数据库 更新: 转载请注明出处:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生). 注:在阅读本文前,请先阅读: 使用IntelliJ ID

这里有一份面筋请查收(八)

本篇是这个系列的最后一篇了,写完这篇就准备离职的相关事情了.这里讲述的是公司简称为A, 是8家面试中唯一挂掉的一家.面试分为4轮,两轮技术,后面两轮应该是BOSS+HR面.HR具有一票否决权.博主只面到2面,就只讲讲这两面面了什么吧. 一面 和其他面试差不多,主要是先针对简历上的内容问一番,然后问点Java基础的问题.(共70mins) 1. CMS什么情况下回发生Serial-Old的操作? CMS收集器无法处理浮动垃圾,可能出现"Concurrent Mode Failure",失

DBSCAN聚类算法原理及其实现

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)聚类算法,它是一种基于高密度连通区域的.基于密度的聚类算法,能够将具有足够高密度的区域划分为簇,并在具有噪声的数据中发现任意形状的簇.我们总结一下DBSCAN聚类算法原理的基本要点: DBSCAN算法需要选择一种距离度量,对于待聚类的数据集中,任意两个点之间的距离,反映了点之间的密度,说明了点与点是否能够聚到同一类中.由于DBSCAN算法对高维数据定义密度很困难,

Guice 3.0 学习 persist jpa

  guice 3.0 的 persist 实现 使用的是 jpa    代码可以从 googlecode 上面下载    http://code.google.com/p/google-guice/downloads/list   guice-3.0-rc3-src.zip   现在还是 beate的版本 但是可以 看api 学习了.   首先 测试使用的是 hsqldb 数据库   jpa 的配置 文件 test/META-INF/persistence.xml   <?xml versio

struts2.0-关于Struts2 DomainDriven

问题描述 关于Struts2 DomainDriven 为何Struts2一直没有自动实例化域 代码如下: jsp <%@ taglib prefix="s" uri="/struts-tags" %> <%-- Created by IntelliJ IDEA. User: 健勤 Date: 2016/2/4 Time: 15:12 To change this template use File | Settings | File Templa

Java中String的hash函数分析

JDK6的源码: /** * Returns a hash code for this string. The hash code for a * <code>String</code> object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using <co