Почему EnumSet или EnumMap могут быть более производительными, чем их хешированные аналоги?

Ниже приведен раздел " Замечания по реализации " документа Java в EnumMap:

Примечание по реализации: Все основные операции выполняются в постоянное время. Вероятно, они (хотя и не гарантированы) будут быстрее, чем их аналоги из HashMap.

Я видел похожую строку в документе Java для EnumSet также. Я хочу знать, почему это более вероятно, что EnumSets а также EnumMaps будет быстрее, чем их хешированные аналоги?

1 ответ

Решение

EnumSet поддерживается битовым массивом. Так как количество различных предметов вы можете положить в EnumSet заранее известно, мы можем просто зарезервировать один бит для каждого значения перечисления. Вы можете представить себе подобную оптимизацию для Set<Byte> или же Set<Short>, но это нереально для Set<Integer> (вам потребуется 0,5 ГБ памяти для 2^32 бит) или вообще.

Таким образом, основные операции, такие как exists или же add постоянное время (так же, как HashSet) но они просто должны изучить или установить один бит. нет hashCode() вычисление. Вот почему EnumSet быстрее. Также более сложные операции, такие как объединение или легко реализуемые с использованием методов манипуляции битами.

В OpenJDK есть две реализации EnumSet: RegularEnumSet способен обрабатывать enum до 64 значений в long а также JumboEnumSet для больших перечислений (используя long[]). Но это просто деталь реализации.

EnumMap работает по аналогичным принципам, но использует Object[] хранить значения, в то время как ключ (индекс) неявно выводится из Enum.ordinal(),

EnumSet использует array[] внутри и естественный порядок с вытекающими отсюда последствиями:

  • быстро: get/set вызывается постоянным временем O(1),hashCode() не используется, чтобы найти нужное ведро
  • эффективность памяти: размер массива предопределен размером Enum и не является динамическим

EnumMap использует Enum в качестве ключа на основе тех же принципов, что и EnumSet где коллизия хэш-кода невозможна

Другие вопросы по тегам