Map.of против EnumMap для неизменяемой карты с ключами enum - PullRequest
0 голосов
/ 11 сентября 2018

EnumMap использует ограничение, что все ключи карты будут из одного и того же enum, чтобы получить выигрыш в производительности:

Enum карты представлены внутри как массивы. Это представление чрезвычайно компактно и эффективно.

В этом случае ключи и значения хранятся в отдельных массивах, а значения упорядочены по порядку. Итерация выполняется с внутренним классом EnumMapIterator.

Неизменяемая карта, созданная различными методами Map.of, использует ограничение, что карта не изменится структурно для получения выигрыша в производительности. Если карта не имеет размера 0 или 1, она использует внутренний класс MapN, который также сохраняет свои записи в массиве. В этом случае значение сохраняется 1 индекс после его ключа. Итерация выполняется с внутренним MapNIterator.

Для неизменной карты enum ключей размером 2 или более, которая отвечает обоим вышеуказанным требованиям, какая карта работает лучше? (Критериями могут быть эффективность использования пространства, эффективность использования времени для containsKey, containsValue, get и эффективность итерации entrySet, keySet и values.)

1 Ответ

0 голосов
/ 12 сентября 2018

какая карта дает лучшую эффективность использования пространства и время для своих операций и итераций: containsKey, containsValue, get, entrySet, keySet и values?

Вы поднимаете 1 + 6 (или 2 * 6, в зависимости от того, как это понимается) вопросы, это слишком много. Если вы хотите получить определенный ответ, вы должны сосредоточиться на одной вещи и профилировать ее (никто не сделает это за вас, если вы не найдете очень интересную проблему).


Эффективность пространства для EnumMap просто должна быть лучше. Нет необходимости хранить ключи, так как можно использовать общий массив перечислений. Нет необходимости в массиве поиска, содержащем дырки .

Могут быть исключения, например, маленькая карта, основанная на огромном перечислении.


Наиболее важной операцией является get. С EnumMap, это не требует поиска , просто тривиальное сравнение классов и доступ к массиву. С Map.of(...) есть цикл , который для перечислений обычно заканчивается после первой итерации, поскольку Enum.hashCode ИМХО глупо , но обычно хорошо распределено.

Поскольку containsKey основан на том же поиске, это ясно.

Сомневаюсь, я когда-либо использовал containsValue, но он не делает ничего умнее, чем линейный поиск. Я бы ожидал небольшой выигрыш для EnumMap из-за дыр (нуждающихся в тривиальном нулевом тесте, но вызывающих неправильные прогнозы ветвления).

Остальные три операции не стоит искать, поскольку они возвращают коллекцию, не содержащую данных и просто указывающую на карту, то есть операцию с постоянным временем. Например, map.keySet().contains(x) просто делегирует map.containsKey().

Эффективность итерации была бы более интересным вопросом, но вы ее не задавали.

...