Подтвердить что ты не робот

HashMap или TreeMap или LinkedHashMap, который быстрее итерации?

У меня есть Map, который заполняется во время запуска приложения. Он не изменяется позже во время выполнения приложения. Позже эта карта используется только для повторения всех элементов в ней. Какую конкретную реализацию Map выбрать? HashMap или TreeMap или LinkedHashMap?
UPDATE
Порядок вставки не имеет значения. Единственное, что имеет значение, это быстрая итерация всех элементов (скажем, 6000 элементов).

4b9b3361

Ответ 1

Ни один из других ответов здесь не учитывает влияние кэша процессора, которое может быть огромным при итерации.

Один из способов улучшить это - использовать только один массив чередующихся ключей и значений (клавиши с четными индексами, значения на нечетных). Это будет тесно группировать эти элементы данных и максимально использовать кеш, по крайней мере, для ссылок.

Но истинное, критическое улучшение было бы достигнуто, если бы вы могли избежать создания объектов, которые хранят ваши данные, и использовать только массивы примитивных значений. Это, естественно, сильно зависит от вашего варианта использования.

Ответ 2

HashMap будет, как правило, самым быстрым, так как он обладает наилучшим поведением кэша (HashMap выполняет итерацию непосредственно над базовым массивом, тогда как TreeMap и LinkedHashMap выполняет итерацию по связанным структурам данных).

Вы можете использовать ImmutableMap или UnmodifiableMap, если карта не изменится после ее инициализации

Ответ 3

Если ваша карта используется только для перебора элементов, и скорость итерации важна, то преобразование карты в ArrayList и повторение ее, это будет самый быстрый способ.

Ответ 4

Я бы не использовал карту. Если все, что вам нужно, - это перебирать записи, создайте новый 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());

Таким образом, вы выполняете итерацию по набору записей только один раз, чтобы создать список. С этого момента вы повторяетесь снова и снова по списку, что, безусловно, должно быть близко к оптимальному.

Примечание Изменено от LinkedList до ArrayList по предложению Марко.

Ответ 5

Я согласен с ответом Zim-Zam и добавляю что-то: если вам нужно получить доступ к ключам и значениям во время итерации, самый быстрый способ - entrySet(), как обсуждалось здесь.

Теперь, если вы уверены, что карта никогда не изменится, почему бы не использовать отдельную структуру данных для итерации? например: повторить по завершенной карте и заполнить ее содержимым пару массивов, один с ключами, а другой со значениями в тех же соответствующих положениях. Тогда перемещение этих массивов будет таким же быстрым, насколько это возможно.

Ответ 6

Map.forEach(BiConsumer) почти всегда быстрее, чем итераторы, иногда с большим отрывом. Если вы суммировали значения, например:

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;
    }
}