2010-05-11 10 views
36

Si consideri il codice di HashMap.clear() follwing:La memoria Java HashMap.clear() e remove() è efficace?

/** 
* Removes all of the mappings from this map. 
* The map will be empty after this call returns. 
*/ 
public void clear() { 
    modCount++; 
    Entry[] tab = table; 
    for (int i = 0; i < tab.length; i++) 
     tab[i] = null; 
    size = 0; 
} 

Sembra, che la matrice interna (table) di Entry oggetti non è mai shrinked. Quindi, quando aggiungo 10000 elementi a una mappa, e dopo quella chiamata map.clear(), manterrà 10000 null nella sua matrice interna. Quindi, la mia domanda è: in che modo JVM gestisce questo array di nulla e, quindi, la memoria dello HashMap è efficace?

+5

10.000 null occupano tutti i 40 KB (possibilmente 80 su una JVM a 64 bit). –

+8

@ Michael, forse, ma è irrilevante: il numero può essere esteso a qualsiasi scala. OP sta chiedendo su una questione di principio. Forse la mappa è enorme, forse la memoria disponibile è piccola. Non lo sappiamo – corsiKa

+2

10000 elementi nella mappa! = 10000 voci nella tabella interna. per favore scopri come funziona l'impl di HashMap ... – james

risposta

57

L'idea è che clear() viene chiamato solo quando si vuole riutilizzare il HashMap. Riutilizzare un oggetto dovrebbe essere fatto solo per lo stesso motivo per cui è stato usato in precedenza, quindi è probabile che tu abbia approssimativamente lo stesso numero di voci. Per evitare il restringimento e il ridimensionamento inutili di Map, la capacità viene mantenuta uguale quando viene chiamato clear().

Se tutto quello che vogliamo fare è scartare i dati nel Map, allora non è necessario (e in realtà non dovrebbe) chiamano clear() su di esso, ma semplicemente cancellare tutti i riferimenti al Map stesso, nel qual caso sarà spazzatura raccolta alla fine

+0

Vorrei anche aggiungere che questo comportamento non fa parte del contratto documentato, quindi anche se ti sei imbattuto in un'implementazione che * ha * ridimensionato l'array interno - che sembra improbabile - allora tu probabilmente non dovrebbe fare affidamento su questo a meno che non lo faccia esplicitamente parte del contratto. –

+1

Va bene, ma cosa succede se la HashMap viene utilizzata in una sorta di singletone e contiene sempre alcuni dati, quindi non può essere sostituita da una nuova istanza? In alcuni casi, può ottenere una grande porzione di dati, che vivranno lì per un po 'di tempo, e successivamente verranno rimossi. Ma i null nella matrice rimarranno. Non sembra a posto. –

+5

@Shaman: tutto ciò che hai appena dato è un'altra ragione per non utilizzare il pattern di singelton ;-) –

4

Hai ragione, ma considerando che aumentare l'array è un'operazione molto più costosa, non è irragionevole pensare che "una volta che l'utente ha aumentato l'array, è probabile che avrà bisogno dell'array di queste dimensioni di nuovo più tardi "e lascia semplicemente la matrice invece di diminuirla e rischiando di doverla espandere in modo espensivo in seguito. Credo che sia euristico: potresti anche difendere il contrario.

4

Un'altra cosa da considerare è che ogni elemento in table è semplicemente un riferimento. L'impostazione di queste voci su null rimuoverà i riferimenti dagli articoli nel tuo Map, che saranno quindi liberi per la garbage collection. Quindi non è come se non si stesse liberando alcun ricordo.

Tuttavia, se è necessario liberare anche la memoria utilizzata dallo stesso Map, è necessario rilasciarlo secondo il suggerimento di Joachim Sauer.

9

Looking at the source code, sembra che HashMap non si restringa mai. Il metodo resize viene chiamato per raddoppiare la dimensione quando richiesto, ma non ha nulla ala ArrayList.trimToSize().

Se stai usando un HashMap in modo tale che cresce e si restringe drammaticamente spesso, si consiglia di creare solo un nuovo HashMap invece di chiamare clear().

Problemi correlati