// Which map you use only chooses the order of the list.
Map<Key,Value> map = new HashMap<>();
// The list to iterate for maximum speed.
List<Map.Entry<Key,Value>> list = new ArrayList<>(map.entrySet());
public class TestForStackOverflow {
int sum = 0;
// Or whatever Map you are using
Map<Object, Integer> map = new HashMap();
static class C implements BiConsumer<Object, Integer> {
int sum = 0;
@Override
public void accept(Object k, Integer v) {
sum += v;
}
}
public int getSum(Map map) {
C c = new C();
map.forEach(c);
return c.sum;
}
public int getSum2(Map map) {
map.forEach((k, v) -> sum += v);
return sum;
}
}
7条答案
按热度按时间5vf7fwbs1#
HashMap
通常是最快的,因为它具有最好的缓存行为(HashMap
直接在后备阵列上迭代,而TreeMap
和LinkedHashMap
在链接的数据结构上迭代)。如果Map在初始化后不会更改,则可能需要使用ImmutableMap或UnmodifiableMap
disho6za2#
这里的其他答案都没有考虑CPU缓存的影响,当涉及迭代时,CPU缓存的影响可能很大。
一种改进方法是只使用一个交错键和值的数组(键在偶数索引,值在奇数索引)。这将把这些数据项紧密地组合在一起,并最大限度地利用该高速缓存,至少对于引用来说是这样。
但是,如果您能够避免创建保存数据的对象,而只使用原始值的数组,那么就可以实现真正的、令人惊叹的改进。当然,这在很大程度上取决于您的用例。
0dxa2lsx3#
我不会用Map。如果你想要的只是迭代条目,创建一个新的
ArrayList
你需要的东西并使用它-你不能得到比ArrayList
更快的迭代。通过这种方式,您只需遍历条目集一次即可构建列表。从那时起,您将一次又一次地遍历列表--这当然应该接近最优。
注根据Marko的建议,从
LinkedList
更改为ArrayList
。5jvtdoz24#
如果你的map只用于迭代元素,迭代的速度很重要,那么把map转换成ArrayList并迭代它,这将是最快的方法。
xiozqbni5#
我同意Zim-Zam的回答,并补充一点:如果在迭代过程中需要同时访问 keys 和 values,最快的方法是使用
entrySet()
方法,如here所讨论的。现在,如果您确定Map永远不会更改,为什么不使用单独的数据结构进行迭代呢?例如:在完成的map上迭代一次,并将其内容填充到两个数组中,一个用键,另一个用值,在相同的对应位置。然后遍历这些数组将尽可能快。
pn9klfpd6#
从Java 10开始,您可以使用
Map.of()
重载方法之一或Map.copyOf()
来创建不可修改的Map。由于这些方法返回的Map不支持将任何新条目放入Map中,因此现有的键/值以this answer中描述的交错模式存储。这应该为您的用例提供最佳性能。owfi6suc7#
Map.forEach(BiConsumer)几乎总是比Iterators快,有时候快很多。例如,如果要对这些值求和: