在Java中使用整数作为HashMap的键
最近,我正在寻找Java API中的在Java中使用整数作为HashMap的键,java,collections,Java,Collections,最近,我正在寻找Java API中的hashCode()方法的良好实现,并查看了Integer源代码。没有料到,但是hashCode()只返回返回返回的int值 public final class Integer ... { private final int value; ... public int hashCode() { return Integer.hashCode(value); } public static int hashCode(in
hashCode()
方法的良好实现,并查看了Integer
源代码。没有料到,但是hashCode()
只返回返回返回的int
值
public final class Integer ... {
private final int value;
...
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
这真的很奇怪,因为有很多论文、页面和软件包专门讨论这个问题——如何设计好散列函数来分配值
最后我得出了这样的结论:
Integer
与HashMap
一起使用时,是键的最差数据类型候选项,因为所有连续键都将放在一个存储箱中。就像上面的例子一样
Map<Integer, String> map = HashMap<>();
for (int i = 1; i < 10; i++) {
map.put(Integer.valueOf(i), "string" + i);
}
Map-Map=HashMap();
对于(int i=1;i<10;i++){
map.put(Integer.valueOf(i),“string”+i);
}
有两个问题,我在谷歌搜索时没有找到答案:
Integer
数据类型,我的结论正确吗Integer的hashCode()
方法不以某种巧妙的方式实现呢当与HashMap一起使用时,Integer是键的最差候选数据类型,因为所有连续键都将放在一个容器中 不,那句话是错的 事实上,
Integer
的hashCode()
的实现是最好的实现。它将每个Integer
值映射到一个唯一的hashCode
值,从而减少不同键映射到同一个bucket中的可能性
有时一个简单的实现是最好的
从Object
类中hashCode()
的Javadoc:
根据java.lang.Object.equals(java.lang.Object)方法,如果两个对象不相等,则对这两个对象中的每一个调用hashCode方法都必须产生不同的整数结果,这不是必需的但是,程序员应该知道,为不相等的对象生成不同的整数结果可能会提高哈希表的性能
Integer
是为数不多的几个类之一,这些类实际上保证不相等的对象将具有与以下对象不同的hashCode()
:
hashCode的总合同为:
每当在Java应用程序的执行过程中对同一对象多次调用hashCode时,hashCode方法必须一致
如果在equals中未使用任何信息,则返回相同的整数
修改对象上的比较。这个整数不需要保留
从应用程序的一次执行到另一次执行的一致性
同样的应用
-->Integer#hashCode
实现了这一点
如果根据equals(Object)方法,两个对象相等,则必须对这两个对象中的每一个调用hashCode方法
生成相同的整数结果
-->Integer#hashCode
也实现了这一点
根据equals(java.lang.Object)方法,如果两个对象不相等,则不需要调用hashCode方法
在两个对象中的每个对象上,必须生成不同的整数结果。
但是,程序员应该知道,生成不同的
不相等对象的整数结果可能会提高
哈希表
-->
Integer#hashCode
最大限度地实现了这一点,即两个不相等的Integer
s将永远不会具有相同的哈希代码 除了@Eran的答案之外,Java的HashMap
还具有防止“坏散列函数”(Integer.hashCode()不是,但仍然是)的功能
因此,使用HashMap时,整数的“简单散列”实际上会有点不同。是的,您的结论是正确的“所有连续键都将放在一个箱子中”-不,一点也不正确。你似乎对炸薯条的工作原理有一些误解。实际上我没有找到答案。我终于从putVal()获得了这种代码的宁静
if((p=tab[I=(n-1)&hash])==null)
/**
* Computes key.hashCode() and spreads (XORs) higher bits of hash
* to lower. Because the table uses power-of-two masking, sets of
* hashes that vary only in bits above the current mask will
* always collide. (Among known examples are sets of Float keys
* holding consecutive whole numbers in small tables.) So we
* apply a transform that spreads the impact of higher bits
* downward. There is a tradeoff between speed, utility, and
* quality of bit-spreading. Because many common sets of hashes
* are already reasonably distributed (so don't benefit from
* spreading), and because we use trees to handle large sets of
* collisions in bins, we just XOR some shifted bits in the
* cheapest possible way to reduce systematic lossage, as well as
* to incorporate impact of the highest bits that would otherwise
* never be used in index calculations because of table bounds.
*/
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}