当前位置: 首页 > 面试题库 >

HashMap通过简单而复杂的键获得性能

孟胤
2023-03-14
问题内容

我想要一张其get操作尽可能快的地图。键是字符串集(数据库中有2个相关的表名),值是整数(数字是数据库中具有表之间实际关系的行的ID),

例如:

table 1 - employee
table 2 - company
relationship - employee.comp_id = company.id

我无意阅读地图中的按键。我只想要给定2个表名称的关系ID。所以我写了一个小程序来测试HashMap中的get操作。

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​​完成块执行所需的时间比块1多大约9倍。

性能是否取决于用作键的对象的复杂性。无论哪种情况,我都知道哈希码是由HasMap.get()方法的实现计算出来的。

实际上,对于块1中的代码,哈希代码是由我的代码以及HashMap的实现来计算的,但性能仍然好于块2,后者中Set的哈希码仅由HashMap的实现来计算。

请注意,两个块中都在创建Set


问题答案:

的性能get()取决于两件事:

  • 参数键对象hashCode()方法的性能
  • 现有关键对象equals()方法的性能

看看的文档HashMap.get()。映射包含键值对。为了找到正确的键值,使用了键的equals()方法。在中HashMap,要比较的键数通过使用哈希值来减少。因此hashCode(),在您作为参数传递的键对象上仅执行一次。

然后,的实现HashMap有几个可能要比较的关键对象(理想情况下只有一个)。这意味着它必须执行equals()1到n次。

如果您具有Setas键类型,则两者都会更复杂,因为它们会迭代Set自身中包含的所有对象。看看执行的equals()hashCode()HashSet和比较它的那些String

以您的示例为例:由于hashCode()恰好执行一次,因此其影响比少equals()。在第一个块中,您需要对其进行一次计算HashSet,然后get()再次对其进行计算Integer(这实际上并不那么复杂)。这在hashCode()零件上没有多大区别。第一个块要快得多,因为equals()执行的是Integer代替HashSet,它要快得多。



 类似资料:
  • 问题内容: 我想要一张其get操作尽可能快的地图。键是字符串集(数据库中有2个相关的表名),值是整数(数字是数据库中具有表之间实际关系的行的ID), 例如: 我无意阅读地图中的按键。我只想要给定2个表名称的关系ID。所以我写了一个小程序来测试HashMap中的get操作。 在我的机器上,块2​​完成块执行所需的时间比块1多大约9倍。 性能是否取决于用作键的对象的复杂性。无论哪种情况,我都知道哈希码

  • 问题内容: 我正在使用具有一些奇怪结构的JSON数据,例如: 我想创建一些JavaScript,将这些数据重组为适当的JSON结构,以使“列”数组值成为“数据”数组值的键。因此,在运行JS进程后,数据类似于以下内容: 完成JSON重组的JavaScript最佳做法是什么?我可以使用JQuery,Foundation JS等JS框架完成此任务吗? 问题答案: newjson是您的新对象,j是您的js

  • 问题内容: 我们习惯说运算是O(1)。但是,这取决于哈希实现。默认对象哈希实际上是JVM堆中的内部地址。我们确定声称 O(1)是否足够好? 可用内存是另一个问题。据我从javadocs理解,应该是0.75。如果我们在JVM中没有足够的内存并且超出限制怎么办? 因此,似乎无法保证O(1)。是有意义还是我想念什么? 问题答案: 这取决于很多事情。这通常是 O(1),一个体面的哈希它本身是固定的时间…但

  • 我对这两种算法的时间复杂度感到困惑。 usingTreeMap算法的时间复杂度正确吗?我知道在treemap中插入时间是log(n ),但是如果我们遍历一个包含10个元素的数组,它会变成nlog(n)吗?

  • 问题内容: 我正在尝试使用HashMap将唯一字符串映射到字符串ArrayList,如下所示: 基本上,我希望能够通过数字访问密钥,而不是使用密钥名称。我希望能够访问所述键的值,以对其进行迭代。我在想像这样的事情: 是否有捷径可寻? 问题答案: 您可以通过调用来遍历键,也可以通过调用来遍历项。遍历条目可能会更快。 如果要确保按插入键的顺序遍历键,请使用。 顺便说一句,我建议将地图的声明类型更改为。