Использование SparseIntArray вместо HashMap <Integer, Integer> с putSeriazable

Когда я использую HashMap с ключом Integer и значениями данных в android, я получаю сообщение в eclipse:

Use new SparseIntArray(...) for better performance

Теперь проблема заключается в том, что SparseIntArray() не реализует интерфейс Seriazable и не может использоваться с .getSerializable() и .putSerializable() в onRestoreInstanceState().

1) Насколько важно использовать SparseIntArray() вместо HashMap?

2) Должен ли я решить проблему сериализации SparseIntArray? (Моя первая идея заключается в создании класса-оболочки, который реализует Serializable, это правильный путь?)

Ответ 1

1) Насколько важно использовать SparseIntArray() вместо HashMap?

Это зависит от того, как вы его используете. Но если вы не пытаетесь представить множество и/или больших "массивов", подобных этому, разница вряд ли будет значительной.

Обратите внимание, что Java SE не имеет разреженных классов массивов, и обычно это не проблема.

2) Должен ли я решить проблему сериализации SparseIntArray? (Моя первая идея заключается в создании класса-оболочки, который реализует Serializable, это правильный путь?)

См. выше и ниже. (Да, это звучит разумно... если вам нужно пойти на это.)


SparseIntArray class (исходный код) использует пару массивов int для представления ключей и значений в сопоставлении и использует двоичный поиск для поиска. Клавиши сохраняются в порядке, не "дыры", а поиск выполняется с помощью двоичного поиска. Это означает следующее:

  • Использование памяти для SparseIntArray будет примерно на 10 раз меньше, чем для эквивалента HashMap. Это связано с комбинацией вещей:

    • массив хеш-таблицы содержит примерно 1 ссылку на запись (в зависимости от того, насколько полная таблица...),

    • ключи и значения должны быть "помечены" в качестве Integer объектов в HashMap и

    • для каждой записи в HashMap требуется объект node, который является довольно тяжелым весом - 4 поля в стандартной реализации.

    (Тем не менее, если вы правильно создаете объекты Integer, то служебные данные "бокса" могут быть смягчены эффектами кеша экземпляров Integer.)

    В отличие от разреженной версии требуется 2 * capacity 4 байтовых слова.

  • Поиск (т.е. get) равен O(logN) по сравнению с O(1) для a HashMap.

  • Случайная вставка O(N) по сравнению с O(1) для a HashMap. (Это связано с тем, что вставка должна перемещаться по средней половине существующих записей, чтобы новая запись могла быть добавлена ​​в правильное положение в массивах.)

  • Последовательная вставка (то есть в порядке возрастания по порядку) O(1).

Итак, "что лучше", очевидно, зависит от того, для чего вы оптимизируете, как вы используете структуру данных и насколько она будет достигнута.

Ответ 2

Проблема с использованием HashMap<Integer, Integer> заключается в том, что каждый ключ и значение должны быть помещены в бокс. Воздействие этого может варьироваться от ничего до тяжелой нагрузки на систему из-за огромного количества выработки мусора и/или использования памяти (не говоря уже о незначительном снижении производительности при боксировании/распаковке значений). (Эти проблемы также привели к разработке нескольких сторонних коллекционных фреймворков для примитивов.)

Если вы решите, что преимущества SparseIntArray заслуживают внимания, то я думаю, что ваш подход класса-оболочки разумен. Альтернативой было бы реализовать его Parcelable, который также можно использовать для сохранения/восстановления состояния экземпляра.