tags:

views:

299

answers:

9

Hello,

I have an array list:

private ArrayList<PerfStatBean> statFilterResults;

I want to iterate through it like:

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

I would like to delete the bean from statFilterResults after I run through it inside the while loop to free up memory. I believe if I do something like

 perfBean = null;

it won't do the job as the perfBean reference will be null but the object will still be in memory.

Any ideas?

Thanks,

Tam

+1  A: 

Create a set before the loop, then add any items to be deleted to that set. After the loop, call

statFilterResults.removeAll(beansToDelete);

Also, and by the way, I find it to be generally easier - more readable, more maintainable, etc. - to use a foreach loop instead of an iterator. In your case, that would look something like:

for (PerfStatBean bean : statFilterResults) {
    ...
}
Carl Manaster
Bonus for the simple answer: clearly the OP had enough RAM to hold the ArrayList (it was populated to begin with). This will make all of that memory available for garbage collecting at once without resorting to attempted hand-tuning.
Bob Cross
This is a bad answer over the simple iterator.remove(). And if you review the implementation of ArrayList (and AbstractList and AbstractCollection), it a doubly bad answer for performance hit.
Software Monkey
@Software Monkey: Nonsense.
Carl Manaster
+1  A: 

iterator.remove()?

toolkit
O(n^2) ...
Tom Hawtin - tackline
+1 for the best and obvious answer. @Tom: Actually, this is far more efficient than throwing the beansToDelete in a set and calling remove all, which calls contains() and remove() for every element in the set. And since the iterator knows exactly where the element is in the list it can remove it directly (no lookup). Lastly, a good list implementation will optimize it's iterator's remove(), or it's removeRange() to take advantage of the specifics of the implementation.
Software Monkey
@Software Monkey: You cannot efficiently remove an element from the middle of an ArrayList (even if you know the position). This involves copying the tail of the array around to shift it.
Thilo
@Thilo: Yes, but this assumes that not all the elements are to be removed, in which case you bear the cost anyway; otherwise he could just clear the list at the end of iterating.
Software Monkey
+1  A: 
ListIterator<PerfStatBean> statsIterator = statFilterResults.iterator();
while(statsIterator.hasNext()){
  i++;
  PerfStatBean perfBean = statsIterator.next();
  ...
  statsIterator.remove();
}
ykaganovich
Nearly: O(n^2)
Tom Hawtin - tackline
@Tom Hawtin Good point, and good answer about set(null) rather than remove. Hard to guess what the OP constraints are. Maybe statFilterResults should be a linkedList; maybe it's not needed after the loop at all and statFilterResults=null is sufficient...
ykaganovich
why is that O(n^2) for ArrayList?
OscarRyz
O(n^2): If you want to remove an element from the middle of an ArrayList, you have to copy/shift the remaining elements. If you need to do this often, consider a LinkedList.
Thilo
@Tom: On what grounds do you make this assertion?
Software Monkey
+1  A: 
while(statsIterator.hasNext()){
  i++;
  PerfStatBean perfBean = statsIterator.next();
  statsIterator.remove();
Laurence Gonsalves
O(n^2) again
Tom Hawtin - tackline
Can you explain why exactly this is O(n^2)?
matt b
O(n^2): If you want to remove an element from the middle of an ArrayList, you have to copy/shift the remaining elements. If you need to do this often, consider a LinkedList.
Thilo
That's true. I hadn't noticed that he specified ArrayList.
Laurence Gonsalves
A: 

In java you don't really need to bother about deleting objects. If there are no references to an object the next time the Garbage Collector runs, it will be deleted (the GC is run when there arefree cpu cycles). If you wish to make sure the object is deleted directly, use Runtime.getRuntime().gc()

Torandi
A: 

I think that other answers have mentioned parts of this answer, but...

From the API:

An Object's finalize() method is "called by the garbage collector on an object when garbage collection determines that there are no more references to the object".

"After the finalize method has been invoked for an object, no further action is taken until the Java virtual machine has again determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, including possible actions by other objects or classes which are ready to be finalized, at which point the object may be discarded."

So basically, the bean will be discarded once there are no more pointers to it. So in your loop, you want to make sure the ArrayList removes its pointer to the bean (this can be done by calling remove() on the iterator within the loop).

snake
+2  A: 

This probably isn't a great optimisation. If the memory requirements are large, then you probably don't want to store them all in a list in the first place - process the objects as they are created.

However, taking the question literally, ListIterator.set is the method for you.

for (
    ListIterator<PerfStatBean> iter = statFilterResults.listIterator();
    iter.hasNext()
) {
    ++i;
    PerfStatBean perfBean = iter.next();
    iter.set(null);
    ...
}
Tom Hawtin - tackline
+1 for storing the iterator, not the list.
snake
+2  A: 

Why not simply clear the list after you have iterated it ?

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

statFilterResults.clear();
nos
A: 

...I would like to delete the bean from statFilterResults after I run through it inside the while loop to free up memory.

If there is another reference of the object outside the arraylist, setting it to null won't make any difference, the memory for that object is used only once, and in java you only see references ( or reference values )

So if you have something like:

this.bean = new PerfStatBean();

....

arrayList.add( this.bean );

Removing it from the list won't make any difference because the original reference will still exists and won't get gc'ed.

If you don't have other references outside the collection ie.

 arrayList.add( new PerfStatBean() );

Then this should be enough:

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

arrayList.clear();

Because that will remove the references to the object and that would make them eligible for gc.

Furthermore: if you want to "help" reduce the number of references an object has, invoking:

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

arrayList.clear();

Should be enough.

OscarRyz