2015-01-16 3 views
16

A HashMap имеет производительность O (1), в то время как состояние переключателя может иметь либо O (1), либо O (log (n)) в зависимости от того, использует ли компилятор коммутатор tableswitch или lookup.Производительность оператора HashMap vs Switch

Вполне понятно, что если переключатель оператор записывается как таковой,

switch (int) { 
    case 1: 
    case 2: 
    case 3: 
    case 4: 
    default: 
} 

, то он будет использовать tableswitch и явно имеют преимущество в производительности по сравнению со стандартным HashMap. Но что, если оператор switch разрежен? Это были бы два примера, которые я бы оценил:

HashMap<Integer, String> example = new HashMap<Integer, String>() {{ 
     put(1, "a"); 
     put(10, "b"); 
     put(100, "c"); 
     put(1000, "d"); 
}}; 

.

switch (int) { 
    case 1: 
     return "a"; 
    case 10: 
     return "b"; 
    case 100: 
     return "c"; 
    case 1000: 
     return "d"; 
    default: 
     return null; 
} 

Что обеспечит большую пропускную способность, поисковый переключатель или HashMap? Означает ли накладные расходы HashMap преимущество lookupswitch раньше, но в конечном итоге сокращается по мере увеличения количества случаев/записей?

Редактировать: Я пробовал некоторые тесты с использованием JMH, вот мои результаты и используемые коды. https://gist.github.com/mooman219/bebbdc047889c7cfe612 Как вы, ребята, упомянули, оператор lookupswitch превзошел HashTable. Я все еще удивляюсь, почему.

+1

Как и почти каждый вопрос о производительности: вы должны его измерить. http://stackoverflow.com/q/504103/139010 Я с нетерпением жду ваших результатов ':)' –

+1

Хороший ответ по умолчанию - сказать вам, чтобы измерить разницу ... Я ожидал бы, что оператор switch будет быстрее, потому что это должно быть меньше инструкций. С C и GCC коммутатор реализуется так, как если/elseif-цепочки, таблицы перехода или то, что не зависит от контекста (например, сколько случаев в коммутаторе, индексирование и т. Д.) –

+1

В дополнение к гораздо меньшей сложности механизм lookupswitch имеет важное преимущество локальности ссылки. Хешмап должен 1. разыменовать ваш ключ Integer; 2. разыщите массив ведра; 3. разыменовать экземпляр узла в массиве по индексу, полученному из 1; 4. разыщите ключ Integer узла, чтобы убедиться, что он равен запрошенному ключу; 5. окончательно разыщите возвращаемое значение из узла. –

ответ

18

Это зависит от многих вещей:

  1. Если есть несколько пунктов/фиксированные элементы. Использование переключателя (наихудший случай O (n))

  2. Если есть много элементов ИЛИ вы хотите добавить будущие элементы без изменения кода ---> Использование хеш-карты (время доступа рассматривается как постоянное время)

  3. Для вашего случая. Вы не должны беспокоиться о производительности, потому что время, потребляемое для обоих случаев, очень низкое. Просто сосредоточьтесь на удобочитаемости/ремонтопригодности вашего кода.

+0

Длина ключа также уместна. – OldCurmudgeon

+0

Почему много элементов плохо для оператора switch? Я слышал, что компилятор делает оптимизацию и бинарное дерево в операторах switch для нас. – shuva

0

В вашем случае, поскольку вы используете Integer ключ для HashMap и равнину «int» для switch заявления, лучшее выполнение реализации станет switch заявления, если количество проходов через этот раздел код очень высок (десятки или сотни тысяч).

Смежные вопросы