这个就是hash算法,对于任意给定的对象,只要它的 hashCode() 返回值相同,那么程序调用 hash(int h) 方法所计算得到的 Hash 码值总是相同的。
1、>>>无符号右移运算符,相对于>>而言,把第一个操作数的二进制码右移指定的位数后,左边空出来的位以原来的符号位来填充,即原来第一个操作数是正数,则左边补0;如果是负则补1;>>>是没有符号的运算符,在把一个二进制码右移之后,左边空的以0来填充
如:[code=java]System.out.println(-5 >> 2);//输出-2
System.out.println(-5 >>> 2);//输出1073741822[/code]--------------------------------------------------------------
比如对于如下的例子让hashMap存储多个数据[code=java]HashMap<String , Double> map = new HashMap<String , Double>();
map.put("数学" , 60.0);
map.put("英语" , 25.0);
map.put("地理" , 12.2); [/code]HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置。
当程序执行 map.put("数学" , 60.0); 时,系统将调用"数学"的 hashCode() 方法得到其 hashCode 值——每个 Java 对象都有 hashCode() 方法,都可通过该方法获得它的 hashCode 值。得到这个对象的 hashCode 值之后,系统会根据该 hashCode 值来决定该元素的存储位置。
HashMap 类的 put(K key , V value) 方法的源代码[code=java]public V put(K key, V value)
{
// 如果 key 为 null,调用 putForNullKey 方法进行处理
if (key == null)
return putForNullKey(value);
// 根据 key 的 keyCode 计算 Hash 值
int hash = hash(key.hashCode());
// 搜索指定 hash 值在对应 table 中的索引
int i = indexFor(hash, table.length);
// 如果 i 索引处的 Entry 不为 null,通过循环不断遍历 e 元素的下一个元素
for (Entry<K,V> e = table; e != null; e = e.next)
{
Object k;
// 找到指定 key 与需要放入的 key 相等(hash 值相同
// 通过 equals 比较放回 true)
if (e.hash == hash && ((k = e.key) == key
|| key.equals(k)))
{
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
// 如果 i 索引处的 Entry 为 null,表明此处还没有 Entry
modCount++;
// 将 key、value 添加到 i 索引处
addEntry(hash, key, value, i);
return null;
} [/code]Map.Entry为hashMap的内部接口,每个 Map.Entry 其实就是一个 key-value 对。从上面程序中可以看出:当系统决定存储 HashMap 中的 key-value 对时,完全没有考虑 Entry 中的 value,仅仅只是根据 key 来计算并决定每个 Entry 的存储位置。这也说明了前面的结论:我们完全可以把 Map 集合中的 value 当成 key 的附属,当系统决定了 key 的存储位置之后,value 随之保存在那里即可。
该方法提供了一个根据 hashCode() 返回值来计算 Hash 码的方法,也就是楼主提出的代码[code=java]static int hash(int h)
{
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
} [/code]这个方法是一个纯粹的数学计算,对于任意给定的对象,只要它的 hashCode() 返回值相同,那么程序调用 hash(int h) 方法所计算得到的 Hash 码值总是相同的
[ 本帖最后由 詹季春 于 2011-07-25 13:30 编辑 ] |