Java TestForNull的映射查找效率

Java TestForNull的映射查找效率,java,performance,dictionary,lookup,Java,Performance,Dictionary,Lookup,使用了一个名为TestForNull的方法。在我被告知可以提高效率之前,这是我的原始代码: 我的原始代码: 在这个片段中,我将对地图进行三次查找。我被告知这只需一次查找即可完成,因此我最终在so上查找答案并找到链接的答案,并将代码修改为: 我的修改代码: 虽然看起来好多了,但在我看来是两次而不是一次。我想知道是否有一个只使用一个的实现,是否可以不使用第三方库来实现。如果有帮助,我正在为我的程序使用HashMap。Java 8在Map接口中添加了许多默认方法,这些方法可能会有所帮助,包括: 以及:

使用了一个名为TestForNull的方法。在我被告知可以提高效率之前,这是我的原始代码:

我的原始代码:

在这个片段中,我将对地图进行三次查找。我被告知这只需一次查找即可完成,因此我最终在so上查找答案并找到链接的答案,并将代码修改为:

我的修改代码:


虽然看起来好多了,但在我看来是两次而不是一次。我想知道是否有一个只使用一个的实现,是否可以不使用第三方库来实现。如果有帮助,我正在为我的程序使用HashMap。

Java 8在Map接口中添加了许多默认方法,这些方法可能会有所帮助,包括:

以及:


进行了适当的优化,以有效地仅执行单个键查找。奇怪的是,TreeMap却不是这样。

@John Kugelman的答案是最好的,只要你能使用java 8

第一个示例的最坏情况是,在已经存在值的情况下,有3个map调用:

康纳斯基 收到 放 第二个示例始终有两个调用和一个空检查:

收到 放 所以你基本上是用containsKey换空支票


在HashMap中,假设哈希代码分布良好,并且该分布与HashMap的大小配合良好,则这些操作的时间大致恒定。其他映射实现(如TreeMap)有logn执行时间。即使在HashMap的情况下,空检查也会比containsKey快,从而使第二个选项成为赢家。但是,除非散列码分布不均匀,或者这是应用程序正在做的唯一事情,或者执行的equals检查不好,否则不可能有可测量的差异

嗯,也许他们的意思是只有查寻?我看不出有任何方法可以进一步缩短这个时间。你的两个代码之间没有区别,真的;或者说,你不知道。这个映射实现的containsKey做了一个完整的检索,可能没有。在那之后,这只是一个选择的问题。但就我个人而言,我会选择第二种解决方案,即修改代码。@fge即使我减少了查找量?如果答案有帮助的话,我使用的是HashMap。你担心什么会花很长时间?计算散列码还是在计算散列码后找到一个空位?如果是第一个,则可以重写hashcode函数以缓存其结果。如果是第二个,则可以增加基础数组的大小。您也可以同时执行这两项操作。@BenjyKessler调用get和put执行两个单独的键查找。对于散列映射,这是两个O1操作,但仍然需要调用两次散列码,并可能搜索两次匹配的bucket。对于树映射,这是两个Olog n操作。OP认为这可以改进是正确的。在实践中,这很少重要,但对我来说,这种问题显示出良好的直觉。如果可以避免的话,为什么要解决问题呢?默认实现也会做同样的事情,但我希望大多数映射实现,特别是HashMap和TreeMap,都有更智能的实现。是的,当然,你是对的。Map的实现无法避免两次查找,但HashMap确实要聪明得多。@LouisWasserman是正确的。HashMap和TreeMap都提供了计算的优化实现。在TreeMap的情况下,它继承了AbstractMap的优化实现,这仍然比2个调用要好得多。显然,我对grepcode中的链接感到困惑。您是对的,TreeMap没有优化的实现。这很奇怪,因为这样做非常简单。我必须更多地研究lambda表达式及其工作原理。您提供给我的答案是一次查找,还是两次查找的改进版本?我看到了这个答案的前一个版本,这表明它与我之前所做的没有太大的不同。考虑到我需要做的事情,我认为使用Java8是可以的,我很感激!。
for (int i = 0; i < temp.length; i++) {
            if (map.containsKey(temp[i]))
                map.put(temp[i], map.get(temp[i]) + 1);
            else
                map.put(temp[i], 1);
for (int i = 0; i < temp.length; i++) {
            Integer value = map.get(temp[i]); 
            if (value != null)
                map.put(temp[i], value + 1);
            else
                map.put(temp[i], 1);
        }
map.merge(temp[i], 1, v -> v + 1);
map.compute(temp[i], (k, v) -> v == null ? 1 : v + 1);