当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

浅谈System.identityHashCode

发表于: 2010-08-20   作者:asialee   来源:转载   浏览次数:
摘要:            今天在查看一下源代码的时候突然发现要调用这个函数的地方,其实如果从定义上面来看的话,感觉不是很明白,说句心里话,我的理解是这样的,它是根据对象的内存地址来生成的hashCode,比如想这么一个情景,一般来说我们都会重载hashCode函数,就那String类的hashCode来说吧,就是与字符串

 

         今天在查看一下源代码的时候突然发现要调用这个函数的地方,其实如果从定义上面来看的话,感觉不是很明白,说句心里话,我的理解是这样的,它是根据对象的内存地址来生成的hashCode,比如想这么一个情景,一般来说我们都会重载hashCode函数,就那String类的hashCode来说吧,就是与字符串的内容有关系,如果我们new两个内容相同的string,那么内存地址肯定是不相同的,那么怎么才能得到原生的hashCode呢,这个函数就是干这个事情的。

      今天其实我看到了一个自己写的数据结构,就是保存一个对象和它的引用计数的。 我看的源代码是hessian,在对象序列化的时候会统计对象的引用情况,比如说Parent类,它被Child引用,它也被GrandParent引用,那么在序列化Child和GrandParent的时候,就有一个数据结构来存储Student对象被引用的情况。所以我就顺便看了一下IdenttityIntMap的函数实现:

  public class IdentityIntMap {
        private Object[] keys;
	private int[] values;

	private int prime;
	private int size;

	public IdentityIntMap(int size) {
		keys = new Object[size];
		values = new int[size];

		prime = findBiggestPrime(size);
		this.size = 0;
	}

	public int get(Object key){
		int hash = System.identityHashCode(key) % prime;
		while(true){
			Object testKey = keys[hash];
			if(testKey == null){
				return -1;
			} else if(testKey == key){
				return values[hash];
			} else {
				hash = (hash + 1) % prime;
			}
		}
	}

	public int put(Object key, int value, boolean replace) {
		int hash = System.identityHashCode(key) % prime;

		while (true) {
			Object testKey = keys[hash];
			if (testKey == null) {
				keys[hash] = key;
				values[hash] = value;
				size++;

				if (keys.length <= 4 * size) {
					resize(4 * keys.length);
				}
				return value;
			} else if (testKey != key) {
				hash = (hash + 1) % prime;
				continue;
			} else if (replace) {
				int old = values[hash];
				values[hash] = value;
				return old;
			}
		}
	}

	public int put(Object key, int value) {
		return put(key, value, true);
	}

	private void resize(int newSize) {
		int[] oldValues = values;
		Object[] oldKeys = keys;
		values = new int[newSize];
		keys = new Object[newSize];
		size = 0;

		prime = findBiggestPrime(newSize);

		for (int i = 0; i < oldKeys.length; i++) {
			if(oldKeys[i] != null){
				put(oldKeys[i], oldValues[i], true);
			}
		}
	}

	public int findBiggestPrime(int value) {
		for (int i = PRIMES.length - 1; i >= 0; i--) {
			if (PRIMES[i] <= value) {
				return PRIMES[i];
			}
		}
		return 2;
	}

	public static final int[] PRIMES = { 1, /* 1<< 0 = 1 */
	2, /* 1<< 1 = 2 */
	3, /* 1<< 2 = 4 */
	7, /* 1<< 3 = 8 */
	13, /* 1<< 4 = 16 */
	31, /* 1<< 5 = 32 */
	61, /* 1<< 6 = 64 */
	127, /* 1<< 7 = 128 */
	251, /* 1<< 8 = 256 */
	509, /* 1<< 9 = 512 */
	1021, /* 1<<10 = 1024 */
	2039, /* 1<<11 = 2048 */
	4093, /* 1<<12 = 4096 */
	8191, /* 1<<13 = 8192 */
	16381, /* 1<<14 = 16384 */
	32749, /* 1<<15 = 32768 */
	65521, /* 1<<16 = 65536 */
	131071, /* 1<<17 = 131072 */
	262139, /* 1<<18 = 262144 */
	524287, /* 1<<19 = 524288 */
	1048573, /* 1<<20 = 1048576 */
	2097143, /* 1<<21 = 2097152 */
	4194301, /* 1<<22 = 4194304 */
	8388593, /* 1<<23 = 8388608 */
	16777213, /* 1<<24 = 16777216 */
	33554393, /* 1<<25 = 33554432 */
	67108859, /* 1<<26 = 67108864 */
	134217689, /* 1<<27 = 134217728 */
	268435399, /* 1<<28 = 268435456 */
	};
}
 

 

下面的是测试方法:

 

 

public class IdentityIntMapTest {
	public static void main(String[] args) {
		IdentityIntMap intMap = new IdentityIntMap(10);
		String aaa = "aaa";
		intMap.put(aaa, 1);
		intMap.put(new String("bbb"), 2);
		intMap.put(new String("ccc"), 3);
		intMap.put(new String("ddd"), 4);
		intMap.put(new String("eee"), 5);

		System.out.println(intMap.get(aaa));
		System.out.println(intMap.get("bbb"));
	}
}

      当时我感觉到intMap.get("bbb")找不到,当时感觉到很奇怪,如果我吧IdentityIntMap的底层实现改成key.hashCode就可以了,但是后来想了一下这个数据结构的使用用途就是这样的我不能顺便修改,把今天的发现记录在这里吧。

浅谈System.identityHashCode

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

推荐文章
11 浅谈
编辑推荐
1.什么是CLR   CLR(Common Language Runtime)公共语言远行时,是一个可由多种编程语言使用的“远
基本情况 在 .NET Framework Base Class Library 的 System 命名空间中定义了 ConsoleColor 枚举,
此文是看到驳:《缓存黄金原则:让数据更靠近CPU》一文有感而发。 为什么要缓存,什么是缓存 先假设
这里先大致介绍一下Hadoop. 本文大部分内容都是从官网Hadoop上来的。其中有一篇介绍HDFS的pdf文档,
  使用Heritrix抓取到自己所需的网页后,还需要对网页中的内容进行分类等操作,这个时候就需要用
首先,我们理解下AJAX的英文含义,AJAX就是(Asynchronous JavaScript And XML),其中文意思就是异
API: Java代码 public interface Executor { void execute(Runnable command); <li style="marg
1.关于编写代码中遇到要同时调用执行几种方法的时候运用线程。 在以前学到的知识中,,我们在一个类
接触IOC也很长时间了,最早是通过spring了解它的,那时候就仅仅停留在使用上,没有过多的去思考它到
支付宝资金平台的迭代从开始到现在,一直在走敏捷的路线,或者说一直在不断尝试各种敏捷路线,尝试-
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号