Java HashMap、TreeMap或LinkedHashMap哪一个迭代最快?

Java HashMap、TreeMap或LinkedHashMap哪一个迭代最快?,java,collections,iteration,Java,Collections,Iteration,我有一张地图,在启动应用程序时填写。在应用程序执行期间,它不会在以后更改。稍后,此映射仅用于迭代其中的所有元素。我应该选择Map的哪个具体实现HashMap或TreeMap或LinkedHashMap? 更新 插入顺序无关紧要。唯一重要的是所有元素的快速迭代(比如6000个元素)。HashMap通常是最快的,因为它具有最好的缓存行为(HashMap直接在备份数组上迭代,而TreeMap和LinkedHashMap在链接数据结构上迭代) 如果地图初始化后不会更改,您可能需要使用or。我同意Zim

我有一张
地图
,在启动应用程序时填写。在应用程序执行期间,它不会在以后更改。稍后,此映射仅用于迭代其中的所有元素。我应该选择
Map
的哪个具体实现
HashMap
TreeMap
LinkedHashMap

更新

插入顺序无关紧要。唯一重要的是所有元素的快速迭代(比如6000个元素)。

HashMap
通常是最快的,因为它具有最好的缓存行为(
HashMap
直接在备份数组上迭代,而
TreeMap
LinkedHashMap
在链接数据结构上迭代)


如果地图初始化后不会更改,您可能需要使用or。我同意Zim Zam的回答,并添加一些内容:如果您需要在迭代过程中访问键和值,最快的方法是使用方法,如前所述


现在,如果您确定地图永远不会改变,为什么不使用单独的数据结构进行迭代呢?例如:在完成的映射上迭代一次,并在相同的对应位置用其内容填充两个数组,一个用键,另一个用值。然后遍历这些数组将尽可能快。

如果您的映射只用于迭代元素,并且迭代速度很重要,那么将映射转换为ArrayList并在其上迭代,这将是最快的方法。

这里的其他答案都没有考虑CPU缓存的影响,当涉及迭代时,它可能是巨大的

改进这一点的一种方法是只使用一个交错键和值的数组(偶数索引的键,奇数索引的值)。这将把这些数据项紧密地组合在一起,并最大限度地利用缓存,至少对于引用是这样


但是,如果您可以避免创建保存数据的对象,而只使用原始值数组,那么真正的、令人尖叫的改进将会实现。当然,这在很大程度上取决于您的用例。

我不会使用地图。如果您只想对条目进行迭代,则创建一个新的
ArrayList
,列出您需要的内容并使用它-对于迭代,您的速度不可能超过
ArrayList

// 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());
//使用哪个映射只选择列表的顺序。
Map Map=newhashmap();
//要以最大速度迭代的列表。
List List=newarraylist(map.entrySet());
这样,您只需在条目集上迭代一次即可构建列表。从那时起,您将一次又一次地在列表中进行迭代,这当然应该接近最优

注意根据Marko的建议,从
LinkedList
更改为
ArrayList

地图。forEach(双消费者)几乎总是比迭代器快,有时甚至比迭代器快很多。例如,如果对值求和:

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;
    }
}
公共类TestForStackOverflow{
整数和=0;
//或者你用的任何地图
Map Map=newhashmap();
静态类C实现双消费者{
整数和=0;
@凌驾
公共void接受(对象k,整数v){
总和+=v;
}
}
公共整数getSum(映射){
C=新的C();
图.forEach(c);
返回c.sum;
}
公共int getSum2(地图){
映射forEach((k,v)->sum+=v);
回报金额;
}
}

从Java 10开始,您可以使用
Map.of()
重载方法或
Map.copyOf()
创建一个。由于这些方法返回的映射不支持将任何新条目放入映射中,因此现有的键/值以交错模式存储,如中所述。这将为您的用例提供最佳性能。

插入顺序无关紧要。唯一重要的是所有元素的快速迭代(比如说6000个元素)。考虑编辑你的帖子,而不是给它添加注释,这很容易错过。请发表你的结果。@ TrasoHoo:我不明白你的意思。请澄清。如何将
HashMap
转换为
ArrayList
Arraylist
将如何存储
Hashmap
键值对?@Mac遍历
Map
entrySet()
,并将键值复制到键值数组中,如我的回答所示。@Mac-简单。创建一个类来保存您的键和值,然后创建该类的ArrayList…@radai该类已经存在,它是
映射中内部使用的
条目
-在任何非映射的上下文中使用Map.Entry(比如他从映射切换到列表)这是否意味着
Hashmap
entrySet()
方法获得的集合的
迭代器将比
树映射的更快?我知道
Hashmap
中的
insert
search
Treemap
快,但我想知道
Iterator
在这两种情况下的性能them@Mac不,这意味着如果使用
entrySet()
返回的集合,遍历映射的速度会更快。另一个问题是,遍历
HashMap
可能比遍历从
HashMap
entrySet()。但是,我可以保证
HashMap
性能会更快吗?您应该运行一个探查器,亲自查看,这是唯一可以确定的方法。我是根据我对类的内部知识来估计相对速度的,但是有很多因素在起作用——不要