HashMap или TreeMap или LinkedHashMap какой из них быстрее перебирать?
у меня есть Map
который заполняется во время запуска приложения. Он не изменяется позже во время выполнения приложения. Позже эта карта используется только для итерации всех элементов в ней. Какая конкретная реализация Map
должен ли я выбрать? HashMap
или TreeMap
или LinkedHashMap
?
обновление
Порядок вставки не имеет значения. Единственное, что имеет значение, - это быстрая итерация всех элементов (скажем, 6000 элементов).
6 ответов
ни один из других ответов здесь не учитывает эффекты кэша процессора, которые могут быть огромный когда речь идет об итерации.
один из способов улучшить это, чтобы использовать только один массив чередующихся ключей и значений (ключи при четных индексах, значения при нечетных). Это позволит плотно сгруппировать эти элементы данных и максимально использовать кэш, по крайней мере для ссылок.
но истинное, кричащее улучшение было бы достигается, если вы можете избежать создания объектов, которые содержат ваши данные и используют только массивы примитивных значений. Это, естественно, сильно зависит от вашего варианта использования.
HashMap
вообще будет быстрым, так как он имеет лучшее поведение кэша (HashMap
выполняет итерацию непосредственно над массивом поддержки, тогда как TreeMap
и LinkedHashMap
перебирать связанные структуры данных).
вы можете использовать ImmutableMap или UnmodifiableMap если карта не изменится после ее инициализации
Если ваша карта используется только для итерации по элементам, и скорость итерации важна, то преобразуйте карту в ArrayList и повторите ее, это будет самый быстрый способ.
Я бы не использовал карту. Если все, что вы хотите, это перебирать записи, сделайте новый 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
to ArrayList
на Марко предложение.
Я согласен с ответом зим-зама и добавляю что-то: если вам нужно получить доступ к обоим ключи и значения во время итерации самый быстрый способ-использовать entrySet()
метод, как описано здесь.
теперь, если вы уверены, что карта никогда не изменится, почему бы не использовать отдельную структуру данных для итерации? например: повторите один раз над готовой картой и заполните ее содержимым пару массивов, один с ключи и другие со значениями, в тех же соответствующих положениях. Тогда пересечение этих массивов будет так же быстро, как он может получить.
Карте.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;
}
}