`
ikon
  • 浏览: 107889 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于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代码
  • 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

    分享到:
    评论

    相关推荐

      定义hashcode时使用31系数的原因

      定义hashcode时使用31系数的原因 Hashcode是一个非常重要的概念在Java编程中,它是用于唯一标识对象的整数值。特别是在使用HashMap、HashSet等集合类时,hashcode的正确实现是非常重要的。本文将详细介绍为什么在...

      关于HashCode码的重复问题 两种验证实例

      1,如果两个对象相同,那么它们的hashCode值一定要相同; 2,如果两个对象的hashCode相同,它们并不一定相同 上面说的对象相同指的是用eqauls方法比较。 3,HashCode码不唯一

      关于hashCode()和equals()的本质区别和联系

      为什么忽略 equals() 和 hashCode() 会带来问题 如果我们忽略 equals() 和 hashCode() 方法,那么我们将不能可靠地检索相关的值,除非我们在 get() 调用中使用与 put() 调用中极其类似的对象实例。这要求确保在我们...

      hashcode和equals方法

      equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.

      HashCode的用法详解

      如果我们不重写 hashCode(),那么对象的 hashCode 将会默认使用 Object 类中的 hashCode 方法,这样将会导致对象的存储位置不确定。 例如,如果我们有两个对象,它们的 hashCode 都是 1,那么它们将会被存放在同一...

      深入 HashCode 方法~

      - 使用 `HashCode` 计算出的索引值可以快速地访问到数组中的某个位置,从而实现快速查找。 2. **HashCode 在哈希表中的应用**: - 在 Java 中,常用的哈希表实现包括 `HashMap` 和 `Hashtable`。 - 这些数据结构...

      hashCode内存溢出和内存泄漏的问题解决.docx

      对于自定义类,尤其是使用了数据传输对象(DTO)的情况下,未正确重写equals和hashCode可能导致内存泄漏。当一个对象被放入哈希集合(如HashSet或HashMap)时,其equals和hashCode方法用于确定对象的身份。如果这两...

      hashcode的作用

      - 在上述示例中,`MyClass` 的 `hashCode()` 方法使用了一个质数(通常是31)来乘以当前的结果,并加上 `attribute1` 和 `attribute2` 的哈希值。这种做法有助于分散哈希值,减少哈希冲突的可能性。 3. **缓存机制...

      hashCode的作用

      如果没有使用`hashCode`,则每次查找特定`ID`对应的`Person`对象时,都需要遍历整个数组,效率较低。而通过使用`hashCode`,可以根据`ID`的值快速定位到对象可能所在的数组位置,大大提高了查找效率。 #### 3. 集合...

      重写equals和hashcode方法_equals_重写equals和hashcode方法_

      - 在 `hashCode()` 方法中,应使用对象的非空关键属性来计算哈希码,以保证不同对象的哈希码尽可能分散。 - 使用现有的工具类,如Java 7引入的`Objects.equals()` 和 `Objects.hash()`,可以减少出错的可能性。 总...

      java中Hashcode的作用.docx

      "Java中Hashcode的作用" Hashcode是Java编程语言中一个非常重要的概念,它在equals方法中扮演着关键角色。在Java中,每个对象都具有一个独特的Hashcode,它可以用来标识对象的身份。但是Hashcode是什么?它是如何...

      解析Java对象的equals()和hashCode()的使用

      深入解析Java对象的equals()和hashCode()的使用 在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个。在多数情况下,这两个函数是不用考虑的,直接使用它们...

      深入HashCode

      《深入HashCode》 在计算机科学领域,特别是在Java和许多其他面向对象编程语言中,`hashCode()`方法是一个至关重要的概念。这个方法是每个对象都具备的,它返回一个整数值,通常用于快速比较对象或者在哈希表(如...

      equals与hashCode方法讲解

      equals 与 hashCode 方法讲解 equals 方法和 hashCode 方法是 Java 语言中两个重要的方法,它们都是在 Object 类中定义的。equals 方法用于比较两个对象是否相等,而 hashCode 方法用于返回对象的哈希码。 在 Java...

      hashcode使用方法

      ### hashcode使用方法 在Java编程语言中,`hashCode` 方法是对象类 `Object` 的一部分,用于生成一个整数,通常用作基于哈希的数据结构(如哈希表)中的索引。为了确保数据结构的高效性,正确地重写 `hashCode` ...

      hashCode方法的使用讲解

      `hashCode`方法是Java编程语言中的一个重要组成部分,主要用于优化数据存储和检索的效率,尤其是在处理大量数据的集合类,如`HashSet`、`HashMap`等。这篇文章将详细讲解`hashCode`方法的作用及其与`equals`方法的...

      Java理论与实践:hashCode()和equals()方法

      本文介绍了Java语言不直接支持关联数组,可以使用任何对象作为一个索引的数组,但在根Object类中使用 hashCode()方法明确表示期望广泛使用HashMap。理想情况下基于散列的容器提供有效插入和有效检索;直接在对象模式...

      HashCode相同equals不同的2位字符集合算法

      在实际编程中,通常推荐使用`Objects`类的`equals()`和`hashCode()`方法,它们提供了安全且一致的实现。例如: ```java public class TwoCharSet { private char char1; private char char2; // 构造器、...

      利用反射绕过编译器和hashcode高级应用

      在Java编程语言中,反射(Reflection)是一种强大的...但需要注意的是,滥用反射可能导致安全问题和性能下降,因此在实际使用中需谨慎权衡。同样,正确实现和使用hashcode也是优化程序性能和保证数据结构正确性的关键。

    Global site tag (gtag.js) - Google Analytics