SparseArray
pode ser usado para substituir HashMap
quando a chave é do tipo primitivo. Existem algumas variantes para diferentes tipos de chave / valor, mesmo que nem todas elas estejam disponíveis publicamente.
Os benefícios são:
- Livre de alocação
- Sem boxe
Desvantagens:
- Geralmente mais lento, não indicado para coleções grandes
- Eles não funcionarão em um projeto que não seja Android
HashMap
pode ser substituído pelo seguinte:
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
Em termos de memória, aqui está um exemplo de SparseIntArray
vs HashMap<Integer, Integer>
para 1000 elementos:
SparseIntArray
:
class SparseIntArray {
int[] keys;
int[] values;
int size;
}
Classe = 12 + 3 * 4 = 24 bytes
Matriz = 20 + 1000 * 4 = 4024 bytes
Total = 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;
}
Classe = 12 + 8 * 4 = 48 bytes
Entrada = 32 + 16 + 16 = 64 bytes
Matriz = 20 + 1000 * 64 = 64024 bytes
Total = 64.136 bytes
Fonte: Memórias Android de Romain Guy, do slide 90.
Os números acima são a quantidade de memória (em bytes) alocada no heap pela JVM. Eles podem variar dependendo da JVM específica usada.
O java.lang.instrument
pacote contém alguns métodos úteis para operações avançadas, como verificar o tamanho de um objeto getObjectSize(Object objectToSize)
.
Informações adicionais estão disponíveis na documentação oficial do Oracle .
Classe = 12 bytes + (n variáveis de instância) * 4 bytes
Matriz = 20 bytes + (n elementos) * (tamanho do elemento)
Entrada = 32 bytes + (tamanho do 1º elemento) + (tamanho do segundo elemento)
Eu vim aqui apenas querendo um exemplo de como usar
SparseArray
. Esta é uma resposta suplementar para isso.Criar um SparseArray
A
SparseArray
mapeia números inteiros para algunsObject
, para que você possa substituirString
no exemplo acima por qualquer outroObject
. Se você estiver mapeando números inteiros para números inteiros, useSparseIntArray
.Adicionar ou atualizar itens
Use
put
(ouappend
) para adicionar elementos à matriz.Observe que as
int
chaves não precisam estar em ordem. Isso também pode ser usado para alterar o valor em umaint
chave específica .Remover itens
Use
remove
(oudelete
) para remover elementos da matriz.O
int
parâmetro é a chave inteira.Valores de pesquisa para uma chave int
Use
get
para obter o valor de alguma chave inteira.Você pode usar
get(int key, E valueIfKeyNotFound)
se quiser evitar obternull
as chaves ausentes.Iterar sobre os itens
Você pode usar
keyAt
evalueAt
algum índice para percorrer a coleção, poisSparseArray
mantém um índice separado e distinto dasint
chaves.Observe que as chaves são ordenadas em valor crescente, não na ordem em que foram adicionadas.
fonte
É apenas um aviso desta documentação da matriz esparsa:
Ele
SparseArray
é feito para ser eficiente em termos de memória do que usar o HashMap regular, ou seja, não permite várias lacunas na matriz, não como o HashMap. Não há nada com o que se preocupar. Você pode usar o HashMap tradicional se não desejar se preocupar com a alocação de memória para o dispositivo.fonte
SparseArray
impede que o número inteiro da chave seja a caixa Automático, que é outra operação e desempenho de custo. ao invés de Mapa será Autobox o inteiro primitivoInteger
Uma matriz esparsa em Java é uma estrutura de dados que mapeia chaves para valores. Mesma idéia que um mapa, mas implementação diferente:
Um mapa é representado internamente como uma matriz de listas, onde cada elemento nessas listas é um par de chave e valor. Tanto a chave quanto o valor são instâncias de objeto.
Uma matriz esparsa é simplesmente composta de duas matrizes: uma matriz de chaves (primitivas) e uma matriz de valores (objetos). Pode haver lacunas nesses índices de matrizes, daí o termo matriz "esparsa".
O principal interesse do SparseArray é que ele economize memória usando primitivas em vez de objetos como chave.
fonte
Depois de pesquisar no Google, tento adicionar algumas informações às respostas já publicadas:
Isaac Taylor fez uma comparação de desempenho para SparseArrays e Hashmaps. Ele afirma que
e
Uma comparação no Edgblog mostra que um SparseArray precisa de muito menos memória que um HashMap devido à chave menor (int vs Integer) e ao fato de que
Como conclusão, eu diria que a diferença pode importar se você deseja armazenar muitos dados no seu Mapa. Caso contrário, apenas ignore o aviso.
fonte
Sim está certo. Mas quando você tem apenas 10 ou 20 itens, a diferença de desempenho deve ser insignificante.
Acho que na maioria das vezes usamos apenas
HashMap
para pesquisar um valor associado a uma chave, enquanto issoSparseArray
é realmente bom nisso.O código fonte do SparseArray é bastante simples e fácil de entender, para que você pague apenas pouco esforço para movê-lo para outras plataformas (através de um simples COPY & Paste).
Tudo o que posso dizer é (para a maioria dos desenvolvedores) quem se importa?
Outro aspecto importante
SparseArray
é que ele usa apenas uma matriz para armazenar todos os elementos enquantoHashMap
usaEntry
, portanto,SparseArray
custa significativamente menos memória que aHashMap
, veja issofonte
É lamentável que o compilador emita um aviso. Eu acho que o HashMap tem sido muito usado para armazenar itens.
SparseArrays tem o seu lugar. Como eles usam um algoritmo de pesquisa binária para encontrar um valor em uma matriz, é necessário considerar o que está fazendo. A pesquisa binária é O (log n) enquanto a pesquisa de hash é O (1). Isso não significa necessariamente que a pesquisa binária seja mais lenta para um determinado conjunto de dados. No entanto, conforme o número de entradas aumenta, o poder da tabela de hash assume o controle. Daí os comentários em que um número baixo de entradas pode ser igual e possivelmente melhor do que usar um HashMap.
Um HashMap é tão bom quanto o hash e também pode ser afetado pelo fator de carga (acho que nas versões posteriores eles ignoram o fator de carga para que possa ser melhor otimizado). Eles também adicionaram um hash secundário para garantir que o hash seja bom. Além disso, o motivo pelo qual o SparseArray funciona muito bem para relativamente poucas entradas (<100).
Eu sugeriria que, se você precisa de uma tabela de hash e deseja um melhor uso da memória para um número inteiro primitivo (sem boxing automático) etc., experimente o trove. ( http://trove.starlight-systems.com - licença LGPL). (Sem afiliação com o trove, assim como sua biblioteca)
Com a construção multi-dex simplificada, temos que você nem precisa reembalar trove para o que você precisa. (trove tem muitas classes)
fonte