避免在 Map 中进行双重查找

问题描述 投票:0回答:1

我有一个性能关键的紧密循环,对于大量键,需要在映射中查找键并使用该键(如果它存在于映射中)执行某些操作:

Map<Integer, SomeClass> map = ...;
for (int i : someLargeIterable)
    if (map.containsKey(i))
        doSomething(i, map.get(i));

如果可能的话,我想避免在地图中查找密钥两次(一次使用

containsKey
,然后再次使用
get
)。可以吗?

如果我可以保证地图不包含空值,我可以这样做:

    var value = map.get(i);
    if (value != null)
        doSomething(i, value);

不幸的是,我不能这样做,因为有时地图可能包含空值,我想将其传递给

doSomething

我想到的一种方法是使用

computeIfPresent

    map.computeIfPresent(i, (key, value) -> {
        doSomething(key, value);
        return value;
    });

但是这会将

value
重新插入到地图中,因此我们再次进行双重查找。是否有类似
computeIfPresent
的东西不会尝试修改地图?也许涉及到
Optional

java
1个回答
0
投票

感谢您对我的问题的评论,我将其总结为未来读者的选项,并给出我自己的其他可能的解决方案(选项 3):

选项1
如果空值很少见,则大多数时候您可以通过仅在值为空时才执行双重查找来避免双重查找:

var value = map.get(i);
if (value != null || map.containsKey(i))
    doSomething(i, value);

选项2
地图中的空值通常是一个坏主意。您可以使用 Null Object 代替空值:

var value = map.get(i);
if (value != null)
    doSomething(i, value == NullObject ? null : value);

选项3 您可以将

getOrDefault
与保证不存在于地图中的默认值一起使用。这样,空值仍然会出现。

var sentinel = new SomeClass(...);  // local variable not in the map
var value = map.getOrDefault(i, sentinel);
if (value != sentinel)  // identity comparison is deliberate; don't use equals()
    doSomething(i, value);
© www.soinside.com 2019 - 2024. All rights reserved.