2009-07-13 6 views
3

Ich habe ein Array Liste ist:nullify Objekt, das Teil von Arraylist java

private ArrayList<PerfStatBean> statFilterResults; 

Ich möchte durchlaufen sie mag:

Iterator<PerfStatBean> statsIterator = statFilterResults.iterator(); 
while(statsIterator.hasNext()){ 
    i++; 
    PerfStatBean perfBean = statsIterator.next(); 
    ......... 

Ich möchte löschen Sie die Bohne aus statFilterResults nachdem ich durchlaufen Sie es innerhalb der while-Schleife, um Speicher freizugeben. Ich glaube, wenn ich etwas tue, wie

perfBean = null; 

wird es nicht die Arbeit machen als die perfBean Referenz null sein wird, aber das Objekt wird noch in Erinnerung sein.

Irgendwelche Ideen?

Danke,

Tam

Antwort

3

Dies ist wahrscheinlich keine große Optimierung. Wenn die Speicheranforderungen groß sind, möchten Sie diese wahrscheinlich nicht alle in einer Liste speichern - verarbeiten Sie die Objekte so, wie sie erstellt werden.

Allerdings ist die Frage wörtlich zu nehmen, ListIterator.set ist die Methode für Sie.

for (
    ListIterator<PerfStatBean> iter = statFilterResults.listIterator(); 
    iter.hasNext() 
) { 
    ++i; 
    PerfStatBean perfBean = iter.next(); 
    iter.set(null); 
    ... 
} 
+0

+1 zum Speichern des Iterators, nicht der Liste. – snake

1

Erstellen Sie einen Satz vor der Schleife, fügen Sie dann alle Elemente in diesem Satz gelöscht werden. Nach der Schleife, rufen

statFilterResults.removeAll(beansToDelete); 

Auch von der Art und Weise, finde ich es in der Regel einfacher zu sein - besser lesbar, besser verwaltbar, usw. - eine foreach-Schleife zu verwenden, anstatt einen Iterators. In Ihrem Fall würde das ungefähr so ​​aussehen:

for (PerfStatBean bean : statFilterResults) { 
    ... 
} 
+1

Bonus für die einfache Antwort: eindeutig hatte das OP genug RAM, um die ArrayList zu halten (es war von Anfang an bevölkert). Dadurch wird der gesamte Speicher für das Sammeln von Müll auf einmal verfügbar, ohne dass versucht wird, manuell zu tunen. –

+0

Dies ist eine schlechte Antwort gegenüber dem einfachen iterator.remove(). Und wenn Sie die Implementierung von ArrayList (und AbstractList und AbstractCollection) überprüfen, ist es eine doppelt schlechte Antwort für Performance-Hit. –

+0

@Software Affe: Unsinn. –

2
+0

O (n^2) ... –

+0

+1 für die beste und offensichtlichste Antwort. @Tom: Eigentlich ist dies viel effizienter als das Werfen der beansToDelete in eine Menge und das Aufrufen von remove all, welche Aufrufe contains() und remove() für jedes Element in der Menge enthalten. Und da der Iterator genau weiß, wo sich das Element in der Liste befindet, kann es es direkt entfernen (kein Nachschlagen). Schließlich optimiert eine gute Listenimplementierung den remove() des Iterators, oder es ist removeRange(), um die Besonderheiten der Implementierung zu nutzen. –

+0

@Software Monkey: Sie können ein Element nicht effizient aus der Mitte einer ArrayList entfernen (selbst wenn Sie die Position kennen). Dazu wird das Ende des Arrays kopiert, um es zu verschieben. – Thilo

1
ListIterator<PerfStatBean> statsIterator = statFilterResults.iterator(); 
while(statsIterator.hasNext()){ 
    i++; 
    PerfStatBean perfBean = statsIterator.next(); 
    ... 
    statsIterator.remove(); 
} 
+0

Fast: O (n^2) –

+0

@ Tom Hawtin Guter Punkt, und gute Antwort über setzen (Null) anstatt zu entfernen. Schwer zu erraten, was die OP-Einschränkungen sind. Vielleicht sollte statFilterResults eine LinkedList sein; vielleicht ist es nach der Schleife überhaupt nicht nötig und statFilterResults = null ist ausreichend ... – ykaganovich

+0

Warum ist das (n^2) für ArrayList? – OscarRyz

1
while(statsIterator.hasNext()){ 
    i++; 
    PerfStatBean perfBean = statsIterator.next(); 
    statsIterator.remove(); 
+0

O (n^2) wieder –

+0

Können Sie erklären, warum genau das O (n^2) ist? –

+0

O (n^2): Wenn Sie ein Element aus der Mitte einer ArrayList entfernen möchten, müssen Sie die übrigen Elemente kopieren/verschieben. Wenn Sie dies häufig tun müssen, sollten Sie eine LinkedList in Betracht ziehen. – Thilo

0

in Java Sie nicht wirklich brauchen, um Löschen von Objekten zu stören. Wenn beim nächsten Ausführen des Garbage Collectors keine Verweise auf ein Objekt vorhanden sind, wird das Objekt gelöscht (der GC wird ausgeführt, wenn es keine CPU-Zyklen gibt). Wenn Sie das Objekt, um sicherzustellen, möchten direkt gelöscht wird, verwenden Runtime.getRuntime(). Gc()

0

Ich denke, dass andere Antworten Teile dieser Antwort erwähnt haben, aber ...

Von der API:

eines Objekts Finalisierung() Methode ist „vom Garbage Collector an einem Objekt aufgerufen, wenn der Garbage collection feststellt, dass es keine weiteren Verweise auf das Objekt gibt“.

„Nachdem die Finalisierung Methode für ein Objekt aufgerufen hat, ist keine weitere Aktion, bis die virtuellen Java- Maschine genommen wird erneut festgestellt, dass dort nicht mehr die Mittel, durch die diese Aufgabe durch eine beliebige zugegriffen werden Thread, der noch nicht gestorben ist, einschließlich möglicher Aktionen durch andere Objekte oder Klassen, die bereit sind, abgeschlossen werden, an welcher Stelle das Objekt verworfen werden kann. "

Also im Grunde wird die Bohne verworfen, sobald es keine Hinweise mehr darauf gibt. In Ihrer Schleife möchten Sie also sicherstellen, dass die ArrayList ihren Zeiger auf die Bean entfernt (dies kann durch Aufrufen von remove() für den Iterator innerhalb der Schleife geschehen).

2

Warum nicht einfach die Liste löschen, nachdem Sie es iteriert haben?

Iterator<PerfStatBean> statsIterator = statFilterResults.iterator(); 
while(statsIterator.hasNext()){ 
    i++; 
    PerfStatBean perfBean = statsIterator.next(); 
    ......... 
} 

statFilterResults.clear(); 
0

... Ich möchte die Bohne von statFilterResults löschen, nachdem ich durch sie innerhalb der while-Schleife laufen Speicher freizugeben.

Wenn es eine andere Referenz des Objekts außerhalb der Arraylist ist, es zu null Einstellung wird keinen Unterschied machen, der Speicher für das Objekt verwendet wird, nur ein einziges Mal, und in Java nur Referenzen sehen (oder Referenz So Werte)

, wenn Sie so etwas wie:

this.bean = new PerfStatBean(); 

.... 

arrayList.add(this.bean); 

es aus der Liste entfernen, wird keinen Unterschied machen, weil die ursprüngliche Referenz noch wird existiert und wird nicht gc'ed erhalten.

Wenn Sie keine anderen Referenzen außerhalb der Sammlung haben, dh.

arrayList.add(new PerfStatBean()); 

Dann sollte das genug sein:

while(....){ 
    .... 
} 

arrayList.clear(); 

Weil das den Verweis auf das Objekt entfernen wird und das würde sie für gc förderfähig machen.

Außerdem:

while(....){ 
    .... 
} 

arrayList.clear(); 

Sollte genug: wenn Sie wollen ein Objekt unter Berufung reduzieren die Anzahl der Referenzen „helfen“.