views:

94

answers:

5

Can anyone tell me if either of these will perform better than the other compiled under Java 1.6? Assume MyObject is a class with one field called listField that has a getter and setter

Sample #1:

MyObject obj = new MyObject();
List<String> lst = new ArrayList<String>(1);
lst.add("Foo");
obj.setListField(lst);

Sample #2:

MyObject obj = new MyObject();
obj.setListField(new ArrayList<String> (1));
obj.getListField().add("Foo");

My thinking is that the creation of a local instance of ArrayList will create memory overhead, but calling getListField() whenever you want to add to the list isn't as fast as accessing a local version of the list. Maybe if there are several items to be added to the list, Sample #1 is faster but with only a few items Sample #2 is faster? Or will the compiler optimize this so that calling getListField() is equivalent to accessing a local version of the list?

+8  A: 

There's no such thing as a "local instance". Assuming setListField() and getListField() are trivial methods, there should be pretty much no performance difference - if any - between these samples. Assuming you're using HotSpot and no subclasses have been loaded which override setListField or getListField, I'd expect the methods to be inlined.

You need to understand that when you call setListField() (again, assuming it's a trivial implementation) you're not creating a copy of the list, or anything like that. You're just passing a reference to the list object. That reference will then be copied into the field. Very cheap. Likewise I'd expect getListField() to simply return the value of the field - a reference to a list. The only thing that gets copied is a reference - 4 or 8 bytes, probably, depending on your JVM.

Personally the first sample looks like cleaner code to me, but you should concentrate on understanding what's going on here as a rather more important matter than performance.

Jon Skeet
Jon, what about the explicit ArrayList size setting to 1? Surely, thats going to cause problems. BTW, you're my hero.
Amir Afghani
@Amir: It's only the initial capacity. Why would it cause any problems? Indeed, there's only one item in the list anyway. Yes, adding the second item to the list would cause it to resize (if the list constructor doesn't enforce a minimum anyway; I haven't checked) but I think that's beyond the scope of this question.
Jon Skeet
@Jon you're right, the ArrayList will be allocated regardless of whether it's set on the MyObject object right away or not. Silly me.To your point about getListField() just returning a memory reference, let's say I needed to copy a string array called myArray to the listField field of a MyObject object and instead of 1 item, the array could have hundreds of items. Would calling obj.getListField().add(myArray[i]) hundreds of times be at all slower than calling lst.add(myArray[i]) and setting lst on myObject afterwards? It seems the overhead of a method call at least would have some impact.
Cameron
@Cameron: Probably not, actually - because the JIT compiler would probably inline it anyway. It's hard to say, but it almost certainly wouldn't be the bottleneck in your code. That's the important thing: write the *cleanest* code first, and measure its performance. *If* you find a bottleneck, micro-optimise just that bit.
Jon Skeet
A: 

IMO the compiler would be smart enough to optimize these two and would make no difference at all.

naikus
A: 

Cameron,

Why are you creating an ArrayList and explicitly sizing it to 1 element? If it will never have more than 1 element in it, don't use a List -- if it will, your performance will be trashed by the list resizing. The issue you brought up, imho, is a non issue.

Amir Afghani
I was initializing the list so that no one would point out that I should be initializing the list size. In my real-world scenario, the list is larger than 1 and I initialize it as such.
Cameron
A: 

I think that the thing to consider is why are you creating an array list with only one element. That way, when you add new elements to that list, the internal array will have to be expanded, which I consider it to be far worse.

By default, ArrayLists are set to 10 elements.

Tom
A: 

Same number of new's => Same performance.

You shouldn't worry about this unless profiling shows this to be a bottleneck

Thorbjørn Ravn Andersen