A questão é (agora) sobre o armazenamento de muitos dados, que podem ser representados usando tipos primitivos como int
, em um mapa. Algumas das respostas aqui são muito enganosas na minha opinião. Vamos ver o porquê.
Modifiquei o benchmark do trove para medir o tempo de execução e o consumo de memória. Também adicionei o PCJ a esse benchmark, que é outra biblioteca de coleções para tipos primitivos (eu uso esse extensivamente). O benchmark 'oficial' do tesouro não compara o IntIntMaps ao Java Collection Map<Integer, Integer>
, provavelmente armazenar Integers
e armazenar ints
não é o mesmo do ponto de vista técnico. Mas um usuário pode não se importar com esses detalhes técnicos, ele deseja armazenar dados representáveis com ints
eficiência.
Primeiro, a parte relevante do código:
new Operation() {
private long usedMem() {
System.gc();
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
// trove
public void ours() {
long mem = usedMem();
TIntIntHashMap ours = new TIntIntHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
ours.put(i, i);
}
mem = usedMem() - mem;
System.err.println("trove " + mem + " bytes");
ours.clear();
}
public void pcj() {
long mem = usedMem();
IntKeyIntMap map = new IntKeyIntOpenHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("pcj " + mem + " bytes");
map.clear();
}
// java collections
public void theirs() {
long mem = usedMem();
Map<Integer, Integer> map = new HashMap<Integer, Integer>(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("java " + mem + " bytes");
map.clear();
}
Presumo que os dados sejam primitivos ints
, o que parece sensato. Mas isso implica em uma penalidade de tempo de execução para o java util, devido ao boxing automático, que não é necessário para as estruturas de coleções primitivas.
Os resultados do tempo de execução (sem gc()
chamadas, é claro) no WinXP, jdk1.6.0_10:
100000 operações de venda 100000 contém operações
coleções java 1938 ms 203 ms
trove 234 ms 125 ms
pcj 516 ms 94 ms
Embora isso possa já parecer drástico, esse não é o motivo para usar essa estrutura.
O motivo é o desempenho da memória. Os resultados para um mapa contendo 100000 int
entradas:
coleções java oscilam entre 6644536 e 7168840 bytes
trove 1853296 bytes
pcj 1866112 bytes
O Java Collections precisa de mais de três vezes a memória em comparação com as estruturas de coleta primitivas. Ou seja, você pode manter três vezes mais dados na memória, sem recorrer às E / S de disco, o que diminui o desempenho do tempo de execução por magnitudes. E isso importa. Leia alta escalabilidade para descobrir o porquê.
Na minha experiência, o alto consumo de memória é o maior problema de desempenho do Java, o que obviamente resulta em pior desempenho do tempo de execução. As estruturas de coleta primitivas podem realmente ajudar aqui.
Então: Não, java.util não é a resposta. E "adicionar funcionalidade" às coleções Java não é o ponto de perguntar sobre eficiência. Além disso, as coleções modernas do JDK " não superam nem as coleções especializadas da Trove".
Isenção de responsabilidade: A referência aqui está longe de ser completa, nem perfeita. O objetivo é esclarecer a questão, que experimentei em muitos projetos. Coleções primitivas são úteis o suficiente para tolerar API duvidosa - se você trabalha com muitos dados.