HashMap通过简单而复杂的密钥获得性能 [英] HashMap get performance with simple and complex key
问题描述
我想要一张get操作尽可能快的地图。
键是字符串集(数据库中有2个表名相关),值是整数(数字是数据库中行的id,表之间有实际关系),
I want a map whose get operation is as fast as possible. The key is set of string (2 table names in database which are related) and value is a integer (the number is id of row in database which has actual relationship between tables),
示例:
table 1 - employee
table 2 - company
relationship - employee.comp_id = company.id
我无意在地图中读取密钥。我只想要给定2个表名的关系id。所以我编写了一个小程序来测试HashMap中的get操作。
I have no intentions to read keys in the map. I just want the relationship id for the given 2 table names. so I wrote a small program to test get operation in HashMap.
public static void main(String args[]) throws NoSuchMethodException, SecurityException {
int limit = 1000;
HashMap<Integer, Integer> m1 = new HashMap<>(1000 * 1000);
HashMap<Set<String>, Integer> m2 = new HashMap<>(1000 * 1000);
String k1, k2;
Set<String> k3;
Integer k4;
for (int x = 0; x < limit; x++) {
for (int y = 0; y < limit; y++) {
k1 = String.valueOf(x);
k2 = String.valueOf(y);
k3 = new HashSet<>(Arrays.asList(k1, k2));
k4 = k3.hashCode();
m2.put(k3, k4);
m1.put(k4, k4);
}
}
long t1, t2;
System.out.println("init");
t1 = System.nanoTime();
// block 1 /////////////////////////////////////////////
for (int x = 0; x < limit; x++) {
for (int y = 0; y < limit; y++) {
m1.get(new HashSet<>(Arrays.asList(String.valueOf(x),
String.valueOf(y))).hashCode());
}
}
// /////////////////////////////////////////////////////
t2 = System.nanoTime();
System.out.println(t2 - t1);
t1 = t2;
// block 2 /////////////////////////////////////////////
for (int x = 0; x < limit; x++) {
for (int y = 0; y < limit; y++) {
m2.get(new HashSet<>(Arrays.asList(String.valueOf(x),
String.valueOf(y))));
}
}
// /////////////////////////////////////////////////////
t2 = System.nanoTime();
System.out.println(t2 - t1);
}
在我的机器上,块2比块大约多9倍的时间1完成执行。
性能是否取决于用作密钥的Object的复杂性。
在任何一种情况下我都知道哈希码是通过HasMap.get()方法的实现来计算的。
Is the performance dependent on complexity of the Object used as key. in either case I know hashcode is calculated by the impementation of HasMap.get() method.
实际上对于块1中的代码,哈希码是由我的代码计算的以及HashMap的实现,但性能仍然优于块2,其中Set的哈希码仅通过实现HashMap计算。
Actually for code in block 1 hashcode is calculated by my code as well as implementation of HashMap, but still the performance is better than block 2 where hashcode of the Set is computed only by implementation of HashMap.
注意Set正在创建在两个块中
notice that Set is being created in both blocks
推荐答案
get()
的性能取决于两个东西:
The performance of get()
depends on two things:
- 参数密钥对象的性能
hashCode()
方法 - 现有密钥对象的性能
equals()
方法
- The performance of the parameter key objects
hashCode()
method - The performance of the existent key objects
equals()
method
看一下 HashMap.get()
的文档。地图包含键值对。要为键找到正确的值,请使用键的 equals()
方法。在 HashMap
中,通过使用它的哈希来减少要比较的键的数量。所以 hashCode()
在您作为参数传递的关键对象上只执行一次。
Take a look at the documentation of HashMap.get()
. A map contains key value pairs. To find the right value for a key, the equals()
method of the key is used. In a HashMap
, the number of keys to compare is reduced by using it's hash. So hashCode()
is executed exactly once on the key object you pass as a parameter.
HashMap
然后有几个可以比较的关键对象(理想情况下只有一个)。这意味着它必须执行 equals()
1到n次。
The implementation of HashMap
then has a couple of possible key objects it has to compare (ideally only one). This means that it has to execute equals()
1 to n times.
如果你有设置
作为键类型,两者都更复杂,因为它们遍历 Set
本身中包含的所有对象。看一下 equals()
和 hashCode()
的实现 HashSet
并将其与 String
进行比较。
If you have a Set
as key type, both are more complex, since they iterate over all objects contained in the Set
itself. Take a look of the implementation of equals()
and hashCode()
of HashSet
and compare it to the ones of String
.
至于你的例子:自 hashCode()
在影响小于 equals()
时执行。在第一个块中,您为 HashSet
计算一次,然后 get()
再次为<$ c $做一次c>整数(实际上并不复杂)。这在 hashCode()
部分中没有太大区别。第一个块快得多,因为等于()
执行 Integer
而不是 HashSet
,这要快得多。
As for your example: Since hashCode()
is executed exactly once it has less impact than equals()
. In your first block you compute it once for HashSet
and then get()
does it once again for Integer
(which isn't really that complex). This doesn't make a lot difference in the hashCode()
part. The first block is a lot faster because equals()
is executed for Integer
instead of HashSet
, which is a lot faster.
这篇关于HashMap通过简单而复杂的密钥获得性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!