SparseArray vs HashMap
Mogę wymyślić kilka powodów, dla których HashMap
S z liczbami całkowitymi są znacznie lepsze niż SparseArray
s:
- dokumentacja Androida dla
SparseArray
mówi " ogólnie jest wolniejszy niż tradycyjnyHashMap
". - jeśli piszesz kod używając
HashMap
s zamiastSparseArray
S, Twój kod będzie działał z innymi implementacjami Map i będziesz mógł używać wszystkich API Javy zaprojektowanych dla map. - jeśli napiszesz kod używając
HashMap
s zamiastSparseArray
S Twój kod będzie działał w innych systemach niż android projekty. - nadpisuje
equals()
ihashCode()
podczas gdySparseArray
Nie.
Jednak za każdym razem, gdy próbuję użyć {[0] } z liczbami całkowitymi w projekcie Androida, IntelliJ mówi mi, że powinienem zamiast tego użyć SparseArray
. Trudno mi to zrozumieć. Czy ktoś zna jakieś istotne powody używania SparseArray
s?
7 answers
SparseArray
Może być używany do wymiany HashMap
kiedy klucz jest prymitywny.
Istnieje kilka wariantów dla różnych typów kluczy/wartości, chociaż nie wszystkie z nich są publicznie dostępne.
Korzyści to:
- bez przydziału
- No boxing
Wady:
- ogólnie wolniejsze, nie wskazane dla dużych zbiorów Nie będą działać w Projekcie non-Android]}
HashMap
może być zastąpiony przez po:
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;
}
Class = 12 + 3 * 4 = 24 bajty
Array = 20 + 1000 * 4 = 4024 bajtów
Razem = 8,072 bajtów
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;
}
Class = 12 + 8 * 4 = 48 bajtów
Wpis = 32 + 16 + 16 = 64 bajty
Array = 20 + 1000 * 64 = 64024 bajtów
Razem = 64 136 bajtów
Źródło: Android Memories by Romain Guy z slide 90.
Powyższe liczby to ilość pamięci (w bajtach) przydzielona na stercie przez JVM. Mogą się one różnić w zależności od konkretnego zastosowanego JVM.
Pakiet java.lang.instrument
zawiera kilka pomocnych metod dla zaawansowanych operacji, takich jak sprawdzanie rozmiaru obiektu za pomocą getObjectSize(Object objectToSize)
.
Dodatkowe informacje są dostępne w oficjalnej dokumentacji Oracle .
Class = 12 bajtów + (N zmiennych instancji) * 4 bajty
Array = 20 bajtów + (n elements) * (Rozmiar elementu)
Wpis = 32 bajty + (1. Rozmiar elementu) + (2. Rozmiar elementu)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-18 21:01:55
Jednak za każdym razem, gdy próbuję użyć Hashmapy z kluczami całkowitymi w Androidzie projekt, intelliJ mówi mi, że powinienem użyć SparseArray zamiast.
Jest to tylko ostrzeżenie z tej dokumentacji z niej:
Ma być bardziej wydajny w pamięci niż używanie Hashmapy do Mapa liczb całkowitych do obiektów
SparseArray
jest wykonana tak, aby była efektywna pamięciowo niż użycie zwykłej Hashmapy, czyli nie pozwala na wielokrotne przerwy w tablica nie jak HashMap. Nie ma się czym martwić możesz użyć tradycyjnej Hashmapy, jeśli nie chcesz martwić się o przydział pamięci do urządzenia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-24 14:56:02
Przyszedłem tu po prostu chcąc przykład jak używać SparseArray
. Jest to odpowiedź uzupełniająca na to pytanie.
Utwórz SparseArray
SparseArray<String> sparseArray = new SparseArray<>();
A SparseArray
mapuje liczby całkowite do niektórych Object
, więc możesz zastąpić String
w powyższym przykładzie dowolnym innym Object
. Jeśli mapujesz liczby całkowite na liczby całkowite, użyj SparseIntArray
.
Dodaj lub zaktualizuj elementy
Użycie put
(lub append
) aby dodać elementy do tablicy.
sparseArray.put(10, "horse");
sparseArray.put(3, "cow");
sparseArray.put(1, "camel");
sparseArray.put(99, "sheep");
sparseArray.put(30, "goat");
sparseArray.put(17, "pig");
Uwaga że klucze int
nie muszą być w porządku. Można to również wykorzystać do zmiany wartości w konkretnym kluczu int
.
Usuń elementy
Użycie remove
(lub delete
) aby usunąć elementy z tablicy.
sparseArray.remove(17); // "pig" removed
Parametr int
jest kluczem całkowitym.
Wyszukiwanie wartości dla klucza int
Użycie get
aby uzyskać wartość dla jakiegoś klucza integer.
String someAnimal = sparseArray.get(99); // "sheep"
String anotherAnimal = sparseArray.get(200); // null
Możesz użyć get(int key, E valueIfKeyNotFound)
jeśli chcesz uniknąć uzyskania null
za brakujące klucze.
Iteracja elementów
Możesz użyć keyAt
oraz valueAt
niektóre indeksy do pętli przez kolekcję, ponieważ SparseArray
utrzymuje oddzielny indeks różniący się od kluczy 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
Zwróć uwagę, że klucze są uporządkowane rosnąco, a nie w kolejności, w jakiej zostały dodane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-21 20:12:54
Rzadka tablica w Javie jest strukturą danych, która mapuje Klucze do wartości. Ten sam pomysł co Mapa, ale inna realizacja:
Mapa jest reprezentowana wewnętrznie jako tablica list, gdzie każdy element w tych listach jest parą kluczy, wartości. Zarówno klucz, jak i wartość są instancjami obiektu.
Sparse array składa się po prostu z dwóch tablic: tablicy kluczy (pierwotnych) i tablicy wartości (obiektów). W tych tablicach mogą występować luki, stąd termin "sparse" array.
Głównym interesem sparsearray jest to, że zapisuje pamięć poprzez użycie prymitywów zamiast obiektów jako klucza.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-04 08:13:45
Po jakimś googlowaniu staram się dodać trochę informacji do już zamieszczonych anwers:
Isaac Taylor zrobił porównanie wydajności dla SparseArrays i Hashmaps. Stwierdza, że
Hashmap i sparsearray są bardzo podobne do struktury danych Rozmiary poniżej 1000
I
Gdy rozmiar został zwiększony do znaku 10 000 [...] Hashmap ma większą wydajność przy dodawaniu obiektów, natomiast sparsearray ma greater wydajność podczas pobierania obiektów. [...] Przy wielkości 100 000 [...] Hashmap bardzo szybko traci wydajność
Porównanie na Edgblog pokazuje, że SparseArray potrzebuje znacznie mniej pamięci niż HashMap ze względu na mniejszy klucz (int vs Integer) i fakt, że
A HashMap.Instancja wejściowa musi śledzić odniesienia do klucz, wartość i następny wpis. Plus musi również przechowywać hash wpisu jako int.
As wniosek powiedziałbym, że różnica może mieć znaczenie, jeśli zamierzasz przechowywać wiele danych na mapie. W przeciwnym razie zignoruj Ostrzeżenie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-12 18:57:12
Tak, to prawda. Ale gdy masz tylko 10 lub 20 elementów, różnica w wydajności powinna być znikoma.Dokumentacja Androida dla sparsearraya mówi: "ogólnie jest wolniej niż tradycyjna Hashmapa".
Jeśli piszesz kod za pomocą HashMaps, a nie SparseArrays swój kod będzie współpracować z innymi implementacjami Map i będziesz mógł używaj wszystkich interfejsów API java zaprojektowanych dla map
Myślę, że najczęściej używamy tylko HashMap
aby wyszukać wartość związaną z kluczem, podczas gdy SparseArray
jest w tym naprawdę dobry.
Jeśli piszesz kod za pomocą HashMaps, a nie SparseArrays swój kod będzie działać w projektach innych niż android.
Kod źródłowy SparseArray jest dość prosty i łatwy do zrozumienia, więc płacisz tylko trochę wysiłku przenosząc go na inne platformy(poprzez prostą Kopiuj i wklej).
Mapa nadpisuje equals () i hashCode (), podczas gdy SparseArray Nie
All I można powiedzieć, (do większości deweloperów)kogo to obchodzi?
Innym ważnym aspektem SparseArray
jest to, że używa tablicy do przechowywania wszystkich elementów, podczas gdy HashMap
używa Entry
, więc SparseArray
kosztuje znacznie mniej pamięci niż HashMap
, zobacz to
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-29 02:29:26
Szkoda, że kompilator wystawia Ostrzeżenie. Domyślam się, że HashMap został nadużyty do przechowywania przedmiotów.
Sparsearray mają swoje miejsce. Biorąc pod uwagę, że używają binarnego algorytmu wyszukiwania, aby znaleźć wartość w tablicy, musisz wziąć pod uwagę, co robisz. Binarne Wyszukiwanie to o (log n), podczas gdy hash lookup 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 hash przejmuje kontrolę. Stąd komentarze, w których mała liczba wpisów może być równa i prawdopodobnie lepsza niż użycie Hashmapy.
HashMap jest tylko tak dobry jak hash i może mieć wpływ na 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 (
Sugerowałbym, że jeśli potrzebujesz tabeli hash i chcesz lepiej wykorzystanie pamięci dla prymitywnej liczby całkowitej (bez auto boksu), itd., wypróbuj trove. ( http://trove.starlight-systems.com - licencja LGPL). (Brak powiązań z trove, podobnie jak ich biblioteka)
Dzięki uproszczonemu budynkowi multi-dex, który mamy, nie musisz nawet przepakowywać skarbca na to, czego potrzebujesz. (trove ma wiele klas)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-02 22:00:09