First, if you’re worried about GC, you can always hang on to the old ArrayList and clear it instead of making a new one.
But there’s no point: 100 ArrayLists every second is never ever ever EVER going to bottleneck your program if you’re running on the desktop, unless you’re either writing literally the most tightly optimized code I’ve ever seen in my life or working with some fantastically large lists.
I ran a quick test, doing a manual filtered ArrayList copy (pretty much exactly as Riven suggested): I started with a 1000 element ArrayList filled with random values between 0 and 1; for each iteration I created a new ArrayList (pre-allocated to the size of the old one so I don’t waste time growing it), and copied elements over unless their values were less than 0.1, in which case I randomly generated new ones. After each iteration I copied the old list into the new one after a clear.
Clearly there’s a lot of inefficient stuff in there, the random calls and the autoboxing; I know this, the point is, you should at least be able to achieve this performance.
I got 17,500 iterations per second on my Macbook Pro using the client JVM. A small GC happened about every 100 iterations, usually taking about .0002 seconds (garbage came from autoboxing).
I tried the same test actually creating new ArrayLists each time, and got very similar results, FWIW.
100 vs. 17,500: That’s not even worth thinking about, let alone optimizing for, unless you’re working on a platform that can’t handle any amount of GC (Android or J2ME, for instance), in which case you’re designing from day one to work around issues like this.
Also, just so we’re being complete, if you really want to alter an ArrayList while you’re iterating over it and don’t want to deal with iterators, it’s easy:
ArrayList<Float> floats = new ArrayList<Float>();
for (int i=0; i < 1000; ++i) {
floats.add(i*1.0f);
}
int i = 0; //handle iteration ourselves, quite manually
while (i < floats.size()) {
if (floats.get(i) % 3 == 0) { //this "evil" comparison actually works, somehow
floats.remove(i);
continue;
}
++i;
}
System.out.println("Not multiples of 3: ");
for (i=0; i<floats.size(); ++i) {
System.out.println(floats.get(i));
}
However, as Riven mentioned, remove calls on ArrayLists are expensive, since they arraycopy the whole tail of the array, and further, floats.size() is not constant so it must be evaluated every time you loop. I’m pretty sure the JVM can optimize away most of those tests as well as most of the bounds checks if you don’t alter the list while iterating.
I didn’t speed test this because it’s bad form anyhow.