HashMap在Java中的内部实现

HashMap在Java中的内部实现,java,hashmap,hash-function,Java,Hashmap,Hash Function,我试图在Java中创建HashMap()的数据结构。HashMap最多只能执行N=1000操作,并且键仅为正整数。我所做的是: class MyHashMap { final ListNode[] nodes = new ListNode[1000]; // "put", "get" and "remove" methods which take // collisions into account using "chaining". } 要决定

我试图在Java中创建
HashMap()
的数据结构。HashMap最多只能执行
N=1000
操作,并且键仅为正整数。我所做的是:

class MyHashMap {
        final ListNode[] nodes = new ListNode[1000];
        // "put", "get" and "remove" methods which take
        // collisions into account using "chaining".
}
要决定新的键值对在
节点中的位置,我总是需要计算一个索引。我使用以下功能:

 public int getIndex(int key) { return Integer.hashCode(key) % nodes.length;}
它返回一个介于
0
节点之间的整数。长度
。但是,我如何用Java自己编写一个Hashfunction,将整数映射到某个索引,而不使用
Integer.hashMap(key)
? 另外,这个过程很好,我不需要代码。

Integer。hashCode(key)
只返回
key
作为结果。你可以写:

public int getIndex(int key) { 
    return key % nodes.length;
}
这样,您就不用使用
Integer.hashCode(key)


如果没有看到类
ListNode
,您的
MyHashMap
结构可能会出现问题,因为您将许多元素设置为同一数组元素。例如,键
3
1003
将保存在同一节点元素中。您必须将
MyHashMap
设计为列表列表(或列表数组或类似的东西)。

首先,
hash
是唯一的或很少重复的值

假设您的值将均匀分布,您可以使用除法的剩余部分作为密钥的哈希值

public int get(int key) {
    return (-1 ^ key) % nodes.length;
}

散列
int
值的一个简单策略是乘以一个大常量。如果不使用常量,则会根据密钥分布获得非常低的冲突率。仍然有可能得到不好的密钥分布,但是对于真实数据来说不太可能

注意:除非您知道密钥不能为负数,否则应使用
Math.abs
确保密钥为非负数

static final int K = 0x7A646E4D; // some large prime.

public int getIndex(int key) { 
    return Math.abs(key * K % nodes.length);
}
一个更快的解决方案是停止使用
%
使用乘法和移位。e、 g

public int getIndex(int key) { 
    return (int) ((key * K & 0xFFFF_FFFFL) * nodes.length >>> 32);
}

这样做的目的是将
键*K
变成一个分数,比使用
%

更快,也许我的问题是什么不太清楚。像我做的那样,Integer.hashCode(key)将返回一个整数值,它可以是所有内容。采用%nodes.length这将确保该值现在有一个在我的数组节点范围内的数字。如果我得到一个与已被占用的单元格相对应的值,我将创建(在我的方法中,这在问题中看不到)到新节点的链接,以防止冲突。所以我并没有你提到的问题。既然可能的话,你还必须考虑碰撞。当然有减少冲突的散列函数,但这不是你的问题。@Giacomo注意:
-1%节点。长度==-1
@PeterLawrey我没有提到键是potive整数,需要编辑它注意:如果
是负数,这可能会返回一个负数。看起来你在乘法后先取最低的32位,最后只取最高的32位。你知道这些东西是怎么解释的吗?e、 g.如何散列一个整数,一个字符串ecc。@MarkoTopolnik在第二个例子中,我从64位值的低位开始,在最后移位32位后,它的作用就像一个分数。@Giacomo所有数据都是数字。你要么有一个像
int
这样的单个值,要么有一个数组或像
char[]
这样的值,这需要一个循环,但原理是一样的。我现在明白了。使用32位数字作为有效范围(0,1)内的比例因子。