Hash算法以及java hashmap的源码分析

        hash算法也叫做散列函数,通过一个函数将任何信息转换成信息量的摘要。一个设计的比较好的hash算法,其冲突是比较少,冲突的含义就是不同的输入经过hash后得到了相同的摘要信息。

        这里我分析了一下java源代码中HashMap的实现。

static int hash(int h) {
        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

        这里可以针对任何类型的对象进行hash计算,之所以传入的是int类型,那是因为java object类中hashcode()方法。该方法的定义也比较有意思。

public native int hashCode(); 说明该方法是c++实现的。因此肯定要加载对应的dll文件。但是这里并没有发现加载什么dll文件。看看java代码里面的加载吧。

private static native void registerNatives();
    static {
        registerNatives();
    }
        我看到这里后,彻底晕倒了。我仅能得到的结论是:hashmap的实现中,java是将key值进行hashcode计算得到int类型,然后再hash计算得到摘要信息。看看hashmap的put方法吧。

 public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }
        这里首先调用了hash(key.hashCode())对key值进行hash,得出的值到table中查询,table是存放所有的值的数组,该数组的包含的对象是Entry对象,这个对象就像链表里面的节点一样。具体可以看看代码了。

        然后对其hash值进行查找,并看table中该索引下的值是否为空,如果不为空的话,则在当前位置的元素中,建立一个链接,新建一个Entry对象,这样,在table数组当前的索引下,就是一个链表了。这是处理冲突的一种方法。如果table中该索引下的值是空的,说明使用正常,不存在冲突。

        需要注意下哦,这里hash出来的值比较大,但是如何把这么大的值直接映射到这么小的数组空间上来呢,在indexFor()方法里面有一些眉目可以看到

 static int indexFor(int h, int length) {
        return h & (length-1);
    }

        经过与计算后,再大的值都会在数组空间范围内了。

        关于java里面的hash就记录到这里了。

        以下有一篇翻译的文章对理解hash比较有帮助。而且记录有各种hash算法。摘录以下代码记录一下。

        http://blog.csdn.net/eaglex/article/details/6310727

 

package com.bplead.hash;



public class Hash {
	
	public static long RSHash(String str){
		int b = 378551;
		int a = 63689;
		long hash = 0;
		for(int i=0;i<str.length();i++){
			hash = hash * a + str.charAt(i);
			a = a +b;
		}
		return hash;
	}
	
	public static long JSHash(String str){  
	      long hash = 1315423911;  
	      for(int i = 0; i < str.length(); i++)  
	      {  
	         hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2));  
	      }  
	      return hash;  
	}  
	
	public long SDBMHash(String str){  
	      long hash = 0;  
	      for(int i = 0; i < str.length(); i++)  
	      {  
	         hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash;  
	      }  
	      return hash;  
	}  
	
	public long DJBHash(String str){  
	      long hash = 5381;  
	      for(int i = 0; i < str.length(); i++)  
	      {  
	         hash = ((hash << 5) + hash) + str.charAt(i);  
	      }  
	      return hash;  
	}  
	
	public long DEKHash(String str){  
	      long hash = str.length();  
	      for(int i = 0; i < str.length(); i++)  
	      {  
	         hash = ((hash << 5) ^ (hash >> 27)) ^ str.charAt(i);  
	      }  
	      return hash;  
	   }  
	
	public static int hash(int h) {
	        // This function ensures that hashCodes that differ only by
	        // constant multiples at each bit position have a bounded
	        // number of collisions (approximately 8 at default load factor).
	        h ^= (h >>> 20) ^ (h >>> 12);
	        return h ^ (h >>> 7) ^ (h >>> 4);
	    }
	
	public static void main(String[] args) {
		String temp = "HelloWorld12";
		int index = hash(temp.hashCode());
		System.out.println(index);
		System.out.println(index&15);
	}
	
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值