SparseArray
kann verwendet werden, um zu ersetzen HashMap
wenn der Schlüssel ein primitiver Typ ist. Es gibt einige Varianten für verschiedene Schlüssel- / Werttypen, obwohl nicht alle öffentlich verfügbar sind.
Vorteile sind:
- Zuteilungsfrei
- Kein Boxen
Nachteile:
- Im Allgemeinen langsamer, für große Sammlungen nicht angegeben
- Sie funktionieren nicht in einem Nicht-Android-Projekt
HashMap
kann durch Folgendes ersetzt werden:
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
In Bezug auf den Speicher ist hier ein Beispiel für SparseIntArray
vs HashMap<Integer, Integer>
für 1000 Elemente:
SparseIntArray
::
class SparseIntArray {
int[] keys;
int[] values;
int size;
}
Klasse = 12 + 3 * 4 = 24 Bytes
Array = 20 + 1000 * 4 = 4024 Bytes
Gesamt = 8.072 Bytes
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;
}
Klasse = 12 + 8 * 4 = 48 Bytes
Eintrag = 32 + 16 + 16 = 64 Bytes
Array = 20 + 1000 * 64 = 64024 Bytes
Gesamt = 64.136 Bytes
Quelle: Android Memories von Romain Guy aus Folie 90.
Die obigen Zahlen geben die von JVM auf dem Heap zugewiesene Speichermenge (in Byte) an. Sie können je nach verwendeter JVM variieren.
Das java.lang.instrument
Paket enthält einige hilfreiche Methoden für erweiterte Vorgänge wie das Überprüfen der Größe eines Objekts mit getObjectSize(Object objectToSize)
.
Zusätzliche Informationen finden Sie in der offiziellen Oracle-Dokumentation .
Klasse = 12 Bytes + (n Instanzvariablen) * 4 Bytes
Array = 20 Bytes + (n Elemente) * (Elementgröße)
Eintrag = 32 Bytes + (1. Elementgröße) + (2. Elementgröße)
Ich kam hierher und wollte nur ein Beispiel für die Verwendung
SparseArray
. Dies ist eine ergänzende Antwort darauf.Erstellen Sie ein SparseArray
A
SparseArray
ordnet einige Ganzzahlen zuObject
, sodass Sie sieString
im obigen Beispiel durch andere ersetzen könnenObject
. Wenn Sie Ganzzahlen Ganzzahlen zuordnen, verwenden SieSparseIntArray
.Elemente hinzufügen oder aktualisieren
Verwenden Sie
put
(oderappend
), um dem Array Elemente hinzuzufügen.Beachten Sie, dass die
int
Schlüssel nicht in Ordnung sein müssen. Dies kann auch verwendet werden, um den Wert an einem bestimmtenint
Schlüssel zu ändern .Teile entfernen
Verwenden Sie
remove
(oderdelete
), um Elemente aus dem Array zu entfernen.Der
int
Parameter ist der Ganzzahlschlüssel.Suchwerte für einen int-Schlüssel
Verwenden Sie
get
diese Option , um den Wert für einen Ganzzahlschlüssel abzurufen.Sie können verwenden,
get(int key, E valueIfKeyNotFound)
wenn Sie vermeiden möchten,null
nach fehlenden Schlüsseln zu suchen.Iterieren Sie über die Elemente
Sie können
keyAt
undvalueAt
einige Indizes verwenden, um die Sammlung zu durchlaufen, da dieSparseArray
einen separaten Index verwaltet, der sich von denint
Schlüsseln unterscheidet.Beachten Sie, dass die Schlüssel in aufsteigender Reihenfolge sortiert sind und nicht in der Reihenfolge, in der sie hinzugefügt wurden.
quelle
Es ist nur eine Warnung aus dieser Dokumentation des spärlichen Arrays:
Das
SparseArray
ist speichereffizient als die Verwendung der regulären HashMap, dh es werden nicht mehrere Lücken innerhalb des Arrays zugelassen, die HashMap nicht ähneln. Sie müssen sich keine Sorgen machen. Sie können die herkömmliche HashMap verwenden, wenn Sie sich keine Gedanken über die Speicherzuordnung zum Gerät machen möchten.quelle
SparseArray
dass verhindert wird , dass die Schlüssel-Ganzzahl Auto-Box ist, was eine weitere Operation und Kostenleistung darstellt . anstatt Karte wird es die primitiven integer AutoBoxInteger
Ein Sparse-Array in Java ist eine Datenstruktur, die Schlüssel Werten zuordnet. Gleiche Idee wie eine Karte, aber andere Implementierung:
Eine Karte wird intern als Array von Listen dargestellt, wobei jedes Element in diesen Listen ein Schlüssel-Wert-Paar ist. Sowohl der Schlüssel als auch der Wert sind Objektinstanzen.
Ein spärliches Array besteht einfach aus zwei Arrays: einem Array aus (primitiven) Schlüsseln und einem Array aus (Objekten) Werten. Es kann Lücken in diesen Array-Indizes geben, daher der Begriff "spärliches" Array.
Das Hauptinteresse des SparseArray besteht darin, dass Speicherplatz gespart wird, indem Primitive anstelle von Objekten als Schlüssel verwendet werden.
quelle
Nach einigem googeln versuche ich, den bereits geposteten Antworten einige Informationen hinzuzufügen:
Isaac Taylor führte einen Leistungsvergleich für SparseArrays und Hashmaps durch. Er behauptet, dass
und
Ein Vergleich in Edgblog zeigt, dass ein SparseArray aufgrund des kleineren Schlüssels (int vs Integer) und der Tatsache, dass ein SparseArray viel weniger Speicher benötigt als eine HashMap
Abschließend würde ich sagen, dass der Unterschied wichtig sein könnte, wenn Sie viele Daten in Ihrer Karte speichern. Andernfalls ignorieren Sie einfach die Warnung.
quelle
Ja, das ist richtig. Wenn Sie jedoch nur 10 oder 20 Elemente haben, sollte der Leistungsunterschied unbedeutend sein.
Ich denke, meistens verwenden wir nur
HashMap
, um einen Wert zu suchen, der einem Schlüssel zugeordnet ist, während diesSparseArray
wirklich gut ist.Der Quellcode von SparseArray ist ziemlich einfach und leicht zu verstehen, so dass Sie nur wenig Aufwand betreiben, um ihn auf andere Plattformen zu verschieben (durch einfaches Kopieren und Einfügen).
Alles was ich sagen kann ist (für die meisten Entwickler), wen interessiert das?
Ein weiterer wichtiger Aspekt
SparseArray
ist , dass es nur ein Array verwendet , um alle Elemente zu speichern , währendHashMap
AnwendungenEntry
, soSparseArray
signifikant weniger Speicher als eine kostenHashMap
, sehen diesequelle
Es ist bedauerlich, dass der Compiler eine Warnung ausgibt. Ich denke, HashMap wurde viel zu oft zum Speichern von Gegenständen verwendet.
SparseArrays haben ihren Platz. Da sie einen binären Suchalgorithmus verwenden, um einen Wert in einem Array zu finden, müssen Sie überlegen, was Sie tun. Die binäre Suche ist O (log n), während die Hash-Suche O (1) ist. Dies bedeutet nicht unbedingt, dass die binäre Suche für einen bestimmten Datensatz langsamer ist. Mit zunehmender Anzahl von Einträgen übernimmt jedoch die Leistung der Hash-Tabelle. Daher die Kommentare, bei denen eine geringe Anzahl von Einträgen gleich und möglicherweise besser sein kann als die Verwendung einer HashMap.
Eine HashMap ist nur so gut wie der Hash und kann auch durch den Auslastungsfaktor beeinflusst werden (ich denke, in späteren Versionen wird der Auslastungsfaktor ignoriert, damit er besser optimiert werden kann). Sie haben auch einen sekundären Hash hinzugefügt, um sicherzustellen, dass der Hash gut ist. Auch der Grund, warum SparseArray für relativ wenige Einträge (<100) sehr gut funktioniert.
Ich würde vorschlagen, wenn Sie eine Hash-Tabelle benötigen und eine bessere Speichernutzung für primitive Ganzzahlen (kein automatisches Boxen) usw. wünschen, probieren Sie trove aus. ( http://trove.starlight-systems.com - LGPL-Lizenz). (Keine Zugehörigkeit zur Fundgrube, genau wie ihre Bibliothek)
Mit dem vereinfachten Multi-Dex-Gebäude, das wir haben, müssen Sie nicht einmal die Fundgrube für das neu verpacken, was Sie brauchen. (Fundgrube hat viele Klassen)
quelle