HashMap通过简单而复杂的密钥获得性能 [英] HashMap get performance with simple and complex key

查看:103
本文介绍了HashMap通过简单而复杂的密钥获得性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一张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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆