38

Using Java (1.6) is it better to call the clear() method on a List or just re-instantiate the reference?

I have an ArrayList that is filled with an unknown number of Objects and periodically "flushed" - where the Objects are processed and the List is cleared. Once flushed the List is filled up again. The flush happens at a random time. The number within the List can potentially be small (10s of Objects) or large (millions of objects).

So is it better to have the "flush" call clear() or new ArrayList() ?

Is it even worth worrying about this sort of issues or should I let the VM worry about it? How could I go about looking at the memory footprint of Java to work this sort of thing out for myself?

Any help greatly appreciated.

braX
  • 11,506
  • 5
  • 20
  • 33
Phil
  • 1,897
  • 4
  • 25
  • 48
  • Note Jon's answer regarding the optimization portion - if you are dealing with high intensity, and there is slowness, then profile it. If the clear is the problem, then you can easily test changing it to creating a new list instead. But otherwise, use what is the most semantically correct - i.e. what the code is actually trying to do. – aperkins Sep 29 '10 at 17:26
  • performance related: [map-clear-vs-new-map-which-one-will-be-better](http://stackoverflow.com/questions/6757868/map-clear-vs-new-map-which-one-will-be-better) – nawfal Jun 02 '14 at 16:14

4 Answers4

36

The main thing to be concerned about is what other code might have a reference to the list. If the existing list is visible elsewhere, do you want that code to see a cleared list, or keep the existing one?

If nothing else can see the list, I'd probably just clear it - but not for performance reasons; just because the way you've described the operation sounds more like clearing than "create a new list".

The ArrayList<T> docs don't specify what happens to the underlying data structures, but looking at the 1.7 implementation in Eclipse, it looks like you should probably call trimToSize() after clear() - otherwise you could still have a list backed by a large array of null references. (Maybe that isn't an issue for you, of course... maybe that's more efficient than having to copy the array as the size builds up again. You'll know more about this than we do.)

(Of course creating a new list doesn't require the old list to set all the array elements to null... but I doubt that that will be significant in most cases.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Visibility not an issue. I like your reasoning for the clear method, since, it helps describe what is going on. I'd never seen trimToSize() before - I'll check that out – Phil Sep 29 '10 at 16:16
  • Also, did you mean the "1.7 implementation"? Surely Eclipse doesn't support Java 1.7 (since it's not out yet) or have I misinterpreted. – Phil Sep 29 '10 at 16:17
  • @Phil: I'm using build 1.7.0-ea-b78. It's the only JVM on this system. Even though it hasn't been released, there have been builds out for it for ages, and Eclipse runs on it with no problems that I've seen. – Jon Skeet Sep 29 '10 at 16:45
  • I was wondering: I used to clear the list and then set it to null - but this is just, because I am not entirely sure what happens if you directly set the list to null (are all elements in that list automatically set to null?), without clearing it first. I want to make sure, that none of the list elements keep "hanging around". – AgentKnopf Mar 27 '12 at 09:51
  • @Zainodis: It entirely depends on whether there are other references to the same objects. But you certainly *don't* need to clear the list *or* set the variable to null, assuming the variable isn't used elsewhere. Setting the variable to null doesn't do *anything* to the list - it's just a variable. Don't forget that there could be other references to the same list. – Jon Skeet Mar 27 '12 at 09:53
  • @JonSkeet So to clarify, clearing the list is better than creating a new list, if perfomance was a factor? – Matt Aug 31 '18 at 14:28
  • @Matt: I would write the clearest code possible to start with. If you're worried about performance, work out concrete performance requirements and measure the options. – Jon Skeet Sep 01 '18 at 07:41
2

The way you are using it looks very much like how a Queue is used. When you work of the items on the queue they are removed when you treat them.

Using one of the Queue classes might make the code more elegant.

There are also variants which handle concurrent updates in a predictable way.

Peter Tillemans
  • 34,983
  • 11
  • 83
  • 114
1

I think if the Arraylist is to be too frequently flushed,like if it's run continuously in loop or something then better use clear if the flushing is not too frequent then you may create a new instance.Also since you say that elements may vary from 10 object to millions you can probably go for an in-between size for each new Arraylist your creating so that the arraylist can avoid resizing a lot of time.

Emil
  • 13,577
  • 18
  • 69
  • 108
1

There is no advantage for list.clear() than new XXList. Here is my investigation to compare performance.

            import java.util.ArrayList;
            import java.util.List;

            public class ClearList {


                public static void testClear(int m, int n) {
                    List<Integer> list = new ArrayList<>();
                    long start = System.currentTimeMillis();

                    for (int i = 0; i < m; i++) {
                        for (int j = 0; j < n; j++) {
                            list.add(Integer.parseInt("" + j + i));
                        }
                        list.clear();
                    }

                    System.out.println(System.currentTimeMillis() - start);
                }

                public static void testNewInit(int m, int n) {
                    List<Integer> list = new ArrayList<>();
                    long start = System.currentTimeMillis();

                    for (int i = 0; i < m; i++) {
                        for (int j = 0; j < n; j++) {
                            list.add(Integer.parseInt("" + j + i));
                        }
                        list = new ArrayList<>();
                    }

                    System.out.println(System.currentTimeMillis() - start);
                }

                public static void main(String[] args) {
                    System.out.println("clear ArrayList:");
                    testClear(991000, 100);
                    System.out.println("new ArrayList:");
                    testNewInit(991000, 100);
                }

            }


            /*--*
             * Out:
             *
             * clear ArrayList:
             * 8391
             * new ArrayList:
             * 6871
            */