Ответ 1
Я думаю, что LinkedHashMap
должен быть быстрее в обход из-за превосходной реализации nextEntry
в своем Iterator
Вот почему:
Пошаговый шаг по пути от реализации values
.
Реализация HashMap
values
такова:
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
}
LinkedHashMap
продолжается от HashMap
и наследует ту же реализацию.
Разница заключается в реализации Iterator
для values
в обоих.
для HashMap
он простирается от java.util.HashMap.HashIterator
private final class ValueIterator extends HashIterator<V> {
public V next() {
return nextEntry().value;
}
}
но для LinkedHashMap
он продолжается от java.util.LinkedHashMap.LinkedHashIterator
private class ValueIterator extends LinkedHashIterator<V> {
public V next() { return nextEntry().value; }
}
поэтому разница существенно сводится к реализации nextEntry
.
Для LinkedHashMap
он просто вызывает e.after, где e - Entry
,
но для HashMap
есть некоторая работа, связанная с перемещением массива Entry[]
, чтобы найти следующий следующий.
UPDATE: Код для nextEntry()
в HashMap
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException();
if ((next = e.next) == null) {
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;
return e;
}
Вступление [] не является непрерывным хранилищем. (Между ними могут быть нулевые значения). Если вы посмотрите на приведенный выше код, то что он делает, это точка рядом с текущим и найти следующий следующий, итерации по записи [].
Но Я думаю, что это увеличение производительности будет зависеть от стоимости вставки. Ознакомьтесь с методом addEntry
в обоих классах как упражнение.