Вопросы производительности для keySet () и entrySet () Map

Все,

Может кто-нибудь, пожалуйста, дайте мне знать точно, какие проблемы с производительностью между 2? Сайт :CodeRanch предоставляет краткий обзор внутренних вызовов, которые понадобятся при использовании keySet () и get (). Но было бы здорово, если бы кто-нибудь мог предоставить точную информацию о потоке, когда используются методы keySet () и get (). Это поможет мне лучше понять проблемы с производительностью.

Ответы на вопрос(1)

Решение Вопроса

Прежде всего, это полностью зависит от того, какой тип карты вы используете. Но поскольку поток JavaRanch говорит о HashMap, я предполагаю, что это реализация, на которую вы ссылаетесь. Предположим также, что вы говорите о стандартной реализации API от Sun / Oracle.

Во-вторых, если вы беспокоитесь о производительности при переборе своей хэш-карты, я предлагаю вам взглянуть наLinkedHashMap, Из документов:

Итерации по представлениям коллекции LinkedHashMap требуют времени, пропорционального размеру карты, независимо от ее емкости. Итерация по HashMap, вероятно, будет более дорогой, требуя времени, пропорционального его емкости.

HashMap.entrySet ()

Исходный код для этой реализации доступен. Реализация в основном просто возвращает новыйHashMap.EntrySet, Класс, который выглядит так:

private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
    public Iterator<Map.Entry<K,V>> iterator() {
        return newEntryIterator(); // returns a HashIterator...
    }
    // ...
}

иHashIterator похоже

private abstract class HashIterator<E> implements Iterator<E> {
    Entry<K,V> next;    // next entry to return
    int expectedModCount;   // For fast-fail
    int index;      // current slot
    Entry<K,V> current; // current entry

    HashIterator() {
        expectedModCount = modCount;
        if (size > 0) { // advance to first entry
            Entry[] t = table;
            while (index < t.length && (next = t[index++]) == null)
                ;
        }
    }

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

    // ...
}

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

HashMap.keySet () и .get ()

Здесь вам сначала нужно получить набор ключей. Это занимает время, пропорциональноевместимость карты (в отличие отразмер для LinkedHashMap). После того, как это сделано, вы звонитеget() один раз для каждого ключа. Конечно, в среднем случае с хорошей реализацией hashCode это занимает постоянное время. Тем не менее, это неизбежно потребует много.hashCode а также.equals звонки, которые, очевидно, займет больше времени, чем простоentry.value() вызов.

 metdos04 мая 2012 г., 12:08
+1 «Итерации по представлениям коллекции LinkedHashMap требуют времени, пропорционального размеру карты, независимо от ее емкости. Итерации по HashMap, вероятно, будут более дорогостоящими, а время пропорционально его емкости».
 ACV05 сент. 2017 г., 11:31
Хороший хороший ответ. Я всегда предпочитаю ссылаться на исходный код, так как это основной источник правды
 sactiw24 янв. 2014 г., 09:31
Но если вам просто нужен доступ к ключам или вам просто нужен доступ к значениям Map, тогда предпочтите итерацию по Set, возвращаемому keySet (), и возвращаемое Collection значение (). Еще один момент, Set, возвращаемый keySet (), и Collection, возвращаемый values ​​(), поддерживаются исходной картой. То есть, если вы внесете в них какие-либо изменения, они будут отражены обратно на карте, однако оба они не поддерживают методы add () и addAll (), т. Е. Вы не можете добавить новый ключ в Set или новое значение. в коллекции.
 Sumit Kumar Saha14 янв. 2016 г., 13:26
@aioobe КАК вы написали: «Это код, определяющий, что произойдет, когда вы выполните итерацию набора записей. Он проходит по всему массиву, который равен емкости карты». Разве это не должно быть "..... который равен размеру карты"?

Ваш ответ на вопрос