Map
アプリケーションの起動中にいっぱいになった があります。後でアプリケーションの実行中に変更されることはありません。後で、このマップはその中のすべての要素を反復するためにのみ使用されます。どの具体的な実装Map
を選択する必要がありますか? HashMap
またはTreeMap
またはLinkedHashMap
?
UPDATE
挿入順序は関係ありません。唯一重要なことは、すべての要素 (たとえば 6000 要素) の高速反復です。
7 に答える
ここでの他の回答はどれも、反復が関係している場合に巨大になる可能性があるCPUキャッシュの影響を考慮していません。
これを改善する 1 つの方法は、インターリーブされたキーと値の配列を1 つだけ使用することです (キーは偶数インデックスに、値は奇数インデックスに)。これにより、これらのデータ項目が緊密にグループ化され、少なくとも参照についてはキャッシュが最大限に活用されます。
しかし、データを保持し、プリミティブ値の配列だけを使用するオブジェクトを作成することを避けることができれば、真に絶大な改善が達成されるでしょう。これは、当然、ユースケースに大きく依存します。
地図は使いません。エントリを繰り返し処理することだけが必要な場合は、必要なものを新しく作成してそれを使用します。繰り返し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());
このようにして、エントリ セットを 1 回だけ反復処理してリストを作成します。それ以降、リスト全体を何度も繰り返します-これは確かに最適に近いはずです。
注Marko の提案でからLinkedList
に変更されました。ArrayList
Map.forEach(BiConsumer) は、ほとんどの場合、Iterator よりも高速であり、場合によっては大幅に高速になります。たとえば、値を合計する場合:
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;
}
}