SparseArray
może służyć do zamiany, HashMap
gdy klucz jest typem pierwotnym. Istnieje kilka wariantów dla różnych typów klucza / wartości, mimo że nie wszystkie z nich są publicznie dostępne.
Korzyści to:
- Bez przydziału
- Żadnego boksu
Wady:
- Generalnie wolniejszy, niewskazany dla dużych kolekcji
- Nie będą działać w projektach innych niż Android
HashMap
można zastąpić następującym:
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
Jeśli chodzi o pamięć, oto przykład SparseIntArray
vs HashMap<Integer, Integer>
dla 1000 elementów:
SparseIntArray
:
class SparseIntArray {
int[] keys;
int[] values;
int size;
}
Klasa = 12 + 3 * 4 = 24 bajty
Tablica = 20 + 1000 * 4 = 4024 bajty
Razem = 8072 bajty
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;
}
Klasa = 12 + 8 * 4 = 48 bajtów
Wpis = 32 + 16 + 16 = 64 bajty
Tablica = 20 + 1000 * 64 = 64024 bajtów
Razem = 64,136 bajtów
Źródło: Android Memories by Romain Guy ze slajdu 90.
Powyższe liczby to ilość pamięci (w bajtach) przydzielona na stercie przez JVM. Mogą się różnić w zależności od używanej maszyny JVM.
java.lang.instrument
Pakiet zawiera kilka przydatnych metod zaawansowanych operacji, takich jak sprawdzenie rozmiaru obiektu z getObjectSize(Object objectToSize)
.
Dodatkowe informacje są dostępne w oficjalnej dokumentacji Oracle .
Klasa = 12 bajtów + (n zmiennych instancji) * 4 bajty
Tablica = 20 bajtów + (n elementów) * (rozmiar elementu)
Entry = 32 bajty + (rozmiar pierwszego elementu) + (rozmiar drugiego elementu)
Przyszedłem tutaj tylko po to, żeby zobaczyć przykład użycia
SparseArray
. To jest dodatkowa odpowiedź.Utwórz SparseArray
A
SparseArray
odwzorowuje liczby całkowite na niektóreObject
, więcString
w powyższym przykładzie można zamienić je na dowolne inneObject
. Jeśli odwzorowujesz liczby całkowite na liczby całkowite, użyjSparseIntArray
.Dodaj lub zaktualizuj elementy
Użyj
put
(lubappend
), aby dodać elementy do tablicy.Pamiętaj, że
int
klucze nie muszą być w porządku. Można to również użyć do zmiany wartości w określonymint
kluczu.Usuń przedmioty
Użyj
remove
(lubdelete
), aby usunąć elementy z tablicy.int
Parametr jest kluczem całkowitą.Wyszukaj wartości dla klucza int
Użyj,
get
aby uzyskać wartość dla jakiegoś klucza całkowitego.Możesz użyć,
get(int key, E valueIfKeyNotFound)
jeśli chcesz uniknąćnull
braku kluczy.Powtarzaj elementy
Możesz użyć
keyAt
ivalueAt
jakiegoś indeksu do zapętlenia kolekcji, ponieważSparseArray
utrzymuje oddzielny indeks różniący się odint
kluczy.Zauważ, że klucze są uporządkowane rosnąco, a nie w kolejności, w jakiej zostały dodane.
źródło
To jest tylko ostrzeżenie z tej dokumentacji o jego rzadkiej tablicy:
Ma
SparseArray
być wydajna pod względem pamięci niż użycie zwykłego HashMap, co oznacza, że nie pozwala na wiele luk w tablicy, w przeciwieństwie do HashMap. Nie ma się czym martwić, możesz skorzystać z tradycyjnej mapy HashMap, jeśli nie chcesz martwić się o alokację pamięci do urządzenia.źródło
SparseArray
że kluczowa liczba całkowita jest automatyczna, co jest kolejną operacją i kosztem wydajności. zamiast Map automatycznie odbije prymitywną liczbę całkowitą naInteger
Rzadka tablica w Javie to struktura danych, która odwzorowuje klucze na wartości. Ten sam pomysł co mapa, ale inna implementacja:
Mapa jest reprezentowana wewnętrznie jako tablica list, gdzie każdy element na tych listach jest parą klucz, wartość. Zarówno klucz, jak i wartość są instancjami obiektu.
Tablica rzadka składa się po prostu z dwóch tablic: tablic (prymitywów) kluczy i tablicy wartości (obiektów). W indeksach tych tablic mogą występować luki, stąd termin „rzadka” tablica.
Główną zaletą SparseArray jest to, że oszczędza pamięć przy użyciu prymitywów zamiast obiektów jako klucza.
źródło
Po pewnym googlowaniu staram się dodać trochę informacji do już opublikowanych odpowiedzi:
Isaac Taylor dokonał porównania wydajności dla SparseArrays i Hashmaps. On uważa, iż
i
Porównanie na Edgblog pokazuje, że SparseArray wymaga znacznie mniej pamięci niż HashMap ze względu na mniejszy klucz (int vs Integer) i fakt, że
Podsumowując, powiedziałbym, że różnica może mieć znaczenie, jeśli zamierzasz przechowywać dużo danych w swojej mapie. W przeciwnym razie po prostu zignoruj ostrzeżenie.
źródło
Tak, to prawda. Ale jeśli masz tylko 10 lub 20 elementów, różnica w wydajności powinna być nieznaczna.
Myślę, że najczęściej używamy tylko
HashMap
do wyszukiwania wartości związanej z kluczem, podczas gdySparseArray
jest w tym naprawdę dobry.Kod źródłowy SparseArray jest dość prosty i łatwy do zrozumienia, dzięki czemu wystarczy niewielki wysiłek, aby przenieść go na inne platformy (za pomocą prostego KOPIUJ i Wklej).
Mogę tylko powiedzieć (większości programistów) kogo to obchodzi?
Innym ważnym aspektem
SparseArray
jest to, że używa on tylko tablicy do przechowywania wszystkich elementów podczasHashMap
używaniaEntry
, więcSparseArray
kosztuje znacznie mniej pamięci niż aHashMap
, zobacz toźródło
Szkoda, że kompilator wyświetla ostrzeżenie. Wydaje mi się, że HashMap był nadużywany do przechowywania przedmiotów.
SparseArrays mają swoje miejsce. Biorąc pod uwagę, że używają binarnego algorytmu wyszukiwania, aby znaleźć wartość w tablicy, musisz rozważyć, co robisz. Wyszukiwanie binarne to O (log n), podczas gdy wyszukiwanie skrótu to O (1). Nie musi to oznaczać, że wyszukiwanie binarne jest wolniejsze dla danego zestawu danych. Jednak wraz ze wzrostem liczby wpisów moc tabeli skrótów przejmuje kontrolę. Stąd komentarze, w których mała liczba wpisów może być równa i prawdopodobnie lepsza niż przy użyciu HashMap.
HashMap jest tak dobry, jak hash, a także może mieć na niego wpływ współczynnik obciążenia (myślę, że w późniejszych wersjach ignorują współczynnik obciążenia, więc można go lepiej zoptymalizować). Dodali również dodatkowy hash, aby upewnić się, że hash jest dobry. Również powód, dla którego SparseArray działa naprawdę dobrze dla stosunkowo niewielu wpisów (<100).
Sugerowałbym, że jeśli potrzebujesz tablicy haszującej i chcesz lepszego wykorzystania pamięci dla prymitywnych liczb całkowitych (bez automatycznego pudełkowania) itp., Wypróbuj trove. ( http://trove.starlight-systems.com - licencja LGPL). (Brak powiązań z skarbnicą, podobnie jak ich biblioteka)
Dzięki uproszczonemu budynkowi multi-dex, który mamy, nie musisz nawet przepakowywać skarbca do tego, czego potrzebujesz. (trove ma wiele klas)
źródło