SparseArray vs HashMap
я могу придумать несколько причин, почему HashMaps с целочисленными ключами намного лучше, чем SparseArrays:
- документация Android для A
SparseArrayговорит: "Это, как правило, медленнее, чем традиционныеHashMap". - если вы пишете код, используя
HashMaps, а неSparseArrays ваш код будет работать с другими реализациями Map, и вы сможете использовать все API Java, предназначенные для карт. - если вы пишете код, используя
HashMaps, а неSparseArrays ваш код будет работать в проектах, отличных от android. - карта переопределяет
equals()иhashCode(), тогда какSparseArrayнет.
но когда я пытаюсь использовать HashMap с целочисленными ключами в проекте Android IntelliJ говорит мне, что я должен использовать SparseArray вместо. Мне очень трудно это понять. Кто-нибудь знает какие-либо веские причины для использования SparseArrays?
7 ответов:
SparseArrayможет использоваться для заменыHashMapкогда ключ является примитивным типом. Существует несколько вариантов для различных типов ключей / значений, хотя не все из них являются общедоступными.преимущества:
- выделение-бесплатно
- бокс
недостатки:
- как правило, медленнее, не указано для большой коллекции
- они не будут работать в не-Android проекта
HashMapможно заменить следующим:SparseArray <Integer, Object> SparseBooleanArray <Integer, Boolean> SparseIntArray <Integer, Integer> SparseLongArray <Integer, Long> LongSparseArray <Long, Object> LongSparseLongArray <Long, Long> //this is not a public class //but can be copied from Android source codeС точки зрения памяти, вот пример
SparseIntArrayvsHashMap<Integer, Integer>на 1000 элементов:
SparseIntArray:class SparseIntArray { int[] keys; int[] values; int size; }класс = 12 + 3 * 4 = 24 байт
Массив = 20 + 1000 * 4 = 4024 байт
Итого = 8,072 байт
HashMap:class HashMap<K, V> { Entry<K, V>[] table; Entry<K, V> forNull; int size; int modCount; int threshold; Set<K> keys Set<Entry<K, V>> entries; Collection<V> values; }класс = 12 + 8 * 4 = 48 байт
Запись = 32 + 16 + 16 = 64 байт
Массив = 20 + 1000 * 64 = 64024 байт
Итого = 64,136 байтисточник: Android Memories by Romain Guy со слайда 90.
числа выше-это объем памяти (в байтах), выделенный в куче JVM. Они могут варьироваться в зависимости от конкретного используемого JVM.
The
java.lang.instrumentпакет содержит некоторые полезные методы для расширенных операций, таких как проверка размера объекта с помощьюgetObjectSize(Object objectToSize).дополнительная информация доступна на официальном документация Oracle.
класс = 12 байт + (n переменных экземпляра) * 4 байта
Массив = 20 байт + (n элементов) * (размер элемента)
Запись = 32 байта + (1-й размер элемента) + (2-й размер элемента)
но всякий раз, когда я пытаюсь использовать HashMap с целочисленными ключами в android проект, intelliJ говорит мне, что я должен использовать SparseArray.
это только предупреждение от документация из него разреженный массив:
Он предназначен для более эффективной памяти, чем использование хэш-карты для сопоставьте целые числа с объектами
The
SparseArrayпроизводится эффективная память чем с помощью обычных HashMap, то есть не допускает несколько пробелов в массиве не так, как HashMap. Там нет ничего, чтобы беспокоиться об этом вы можете использовать традиционный HashMap, если вы хотите не беспокоиться о выделении памяти на устройство.
я пришел сюда, просто хотел пример того, как использовать
SparseArray. Это дополнительный ответ.создать SparseArray
SparseArray<String> sparseArray = new SparseArray<>();A
SparseArrayсопоставляет целые числа некоторымObject, так что вы могли бы заменитьStringв приведенном выше примере с любым другимObject. Если вы сопоставляете целые числа с целыми числами, то используйтеSparseIntArray.добавить или обновить элементы
использовать
put(илиappend) для добавления элементов в массив.sparseArray.put(10, "horse"); sparseArray.put(3, "cow"); sparseArray.put(1, "camel"); sparseArray.put(99, "sheep"); sparseArray.put(30, "goat"); sparseArray.put(17, "pig");отметим, что
intключи не должны быть в порядке. Это также может быть использовано для изменения значения в определенномintключ.удалить элементы
использовать
remove(илиdelete) для удаления элементов из массива.sparseArray.remove(17); // "pig" removedThe
intпараметр-это целочисленный ключ.поиск значений для int ключ
использовать
getчтобы получить значение для некоторого целого ключа.String someAnimal = sparseArray.get(99); // "sheep" String anotherAnimal = sparseArray.get(200); // nullможно использовать
get(int key, E valueIfKeyNotFound)если вы хотите избежатьnullдля отсутствующих ключей.перебирать элементы
можно использовать
keyAtиvalueAtнекоторый индекс для цикла через коллекцию, потому чтоSparseArrayподдерживает отдельный индекс, отличный отintключи.int size = sparseArray.size(); for (int i = 0; i < size; i++) { int key = sparseArray.keyAt(i); String value = sparseArray.valueAt(i); Log.i("TAG", "key: " + key + " value: " + value); } // key: 1 value: camel // key: 3 value: cow // key: 10 value: horse // key: 30 value: goat // key: 99 value: sheepобратите внимание, что ключи упорядочены по возрастанию стоимости, не в том порядке, в котором они были добавлены.
разреженный массив в Java-это структура данных, которая отображает ключи на значения. Та же идея, что и карта, но другая реализация:
карта представлена внутренне в виде массива списков,где каждый элемент в этих списках является парой ключ-значение. И ключ, и значение являются экземплярами объекта.
разреженный массив просто состоит из двух массивов: массивов (примитивов) ключей и массива (объектов) значений. В этих массивах могут быть пробелы индексы, отсюда и термин "разреженный" массив.
основной интерес SparseArray заключается в том, что он экономит память, используя примитивы вместо объектов в качестве ключа.
после некоторого googling я пытаюсь добавить некоторую информацию к уже опубликованным anwers:
Исаак Тейлор сделано сравнение производительности для разреженных лучей и хэш-карт. Он утверждает, что
Hashmap и SparseArray очень похожи для структуры данных размеры под 1000
и
когда размер был увеличен до отметки 10 000 [...] хэш-карта имеет большую производительность при добавлении объекты, в то время как SparseArray имеет повышенная производительность при извлечении объектов. [...] В размере 100 000 [...] Hashmap теряет производительность очень быстро
в сравнении с Edgblog показывает, что SparseArray требуется гораздо меньше памяти, чем HashMap из-за меньшего ключа (int vs Integer) и того факта, что
HashMap.Экземпляр записи должен отслеживать ссылки для ключ, значение и следующая запись. Кроме того, он также необходимо хранить хэш-записи как int.
в качестве вывода я бы сказал, что разница может иметь значение, если вы собираетесь хранить много данных на своей карте. В противном случае просто игнорируйте предупреждение.
в документации android для SparseArray говорится: "это вообще медленнее, чем традиционный HashMap".
Да,это. Но когда у вас есть только 10 или 20 штук , разница в производительности должна быть незначительной.
если вы пишете код с помощью хэш-карт, а не SparseArrays ваш код будет работать с другими реализациями карты и вы сможете использовать все API-интерфейсы Java, предназначенные для Карты
Я думаю, что чаще всего мы используем только
HashMapдля поиска значения, связанного с ключом в то время какSparseArrayэто действительно хорошо.если вы пишете код с помощью хэш-карт, а не SparseArrays ваш код будет работать в не android проектах.
исходный код SparseArray довольно прост и понятен, так что вы только платите немного усилий, перемещая его на другие платформы(через простое копирование и вставку).
карта переопределяет equals () и hashCode (), тогда как SparseArray не
все что я могу сказать, (для большинства разработчиков), кто заботится?
еще один важный аспект
SparseArrayзаключается в том, что он использует только массив для хранения всех элементов, в то время какHashMapиспользуетEntry, так чтоSparseArrayстоит значительно меньше памяти, чем aHashMapсм. этой
к сожалению, компилятор выдает предупреждение. Я думаю, что HashMap был чрезмерно использован для хранения элементов.
редкие лучи имеют свое место. Учитывая, что они используют алгоритм двоичного поиска, чтобы найти значение в массиве, вы должны рассмотреть, что вы делаете. Двоичный поиск за o(зарегистрируйте N), в то время как хэш-поиска составляет O(1). Это не обязательно означает, что двоичный поиск медленнее для данного набора данных. Однако по мере роста числа записей мощность хэш-таблицы принимает свыше. Следовательно, комментарии, где низкое количество записей может равняться и, возможно, быть лучше, чем с помощью хэш-карты.
HashMap только так хорош, как хэш, а также может быть подвержен влиянию фактора нагрузки (я думаю, что в более поздних версиях они игнорируют фактор нагрузки, поэтому он может быть лучше оптимизирован). Они также добавили вторичный хэш, чтобы убедиться, что хэш хорош. Также причина SparseArray работает очень хорошо для относительно немногих записей (
Я бы предположил, что если вам нужен хэш таблица и хотите лучше использовать память для примитивного целого числа (без автоматического бокса) и т. д.- попробуй копать. (http://trove.starlight-systems.com - лицензия LGPL). (Нет связи с trove, как и их библиотека)
с упрощенным зданием multi-dex у нас есть вам даже не нужно переупаковывать клад для того, что вам нужно. (trove имеет много классов)
Comments