tags:

views:

2902

answers:

10

I usually always find it sufficient to use the concrete classes for the interfaces listed in the title. Usually when I use other types (such as LinkedList or TreeSet), the reason is for functionality and not performance - for example, a LinkedList for a queue.

I do sometimes construct ArrayList with an initial capcacity more than the default of 10 and a HashMap with more than the default buckets of 16, but I usually (especially for business CRUD) never see myself thinking "hmmm...should I use a LinkedList instead ArrayList if I am just going to insert and iterate through the whole List?"

I am just wondering what everyone else here uses (and why) and what type of applications they develop.

+1  A: 

Having just come out of a class about data structure performance, I'll usually look at the kind of algorithm I'm developing or the purpose of the structure before I choose an implementation.

For example, if I'm building a list that has a lot of random accesses into it, I'll use an ArrayList because its random access performance is good, but if I'm inserting things into the list a lot, I might choose a LinkedList instead. (I know modern implementations remove a lot of performance barriers, but this was the first example that came to mind.)

You might want to look at some of the Wikipedia pages for data structures (especially those dealing with sorting algorithms, where performance is especially important) for more information about performance, and the article about Big O notation for a general discussion of measuring the performance of various functions on data structures.

Tim
+9  A: 

Those are definitely my default, although often a LinkedList would in fact be the better choice for lists, as the vast majority of lists seem to just iterate in order, or get converted to an array via Arrays.asList anyway.

But in terms of keeping consistent maintainable code, it makes sense to standardize on those and use alternatives for a reason, that way when someone reads the code and sees an alternative, they immediately start thinking that the code is doing something special.

I always type the parameters and variables as Collection, Map and List unless I have a special reason to refer to the sub type, that way switching is one line of code when you need it.

I could see explicitly requiring an ArrayList sometimes if you need the random access, but in practice that really doesn't happen.

Yishai
Even if you just iterate, an ArrayList is usually better, because it has less memory overhead.
Michael Borgwardt
+1 for ALWAYS ALWAYS ALWAYS using the interface class unless you have a good reason not too. I fixed a real world problem by converting an implementation using List (backed by ArrayList) to a CopyOnWriteArrayList. One line fix. Always use interfaces.
basszero
@Michael, good point, but unstated in my writing was that it is more common to add to the list and not know its size than to pull a specific numbered element. But I still use ArrayList by default.
Yishai
@basszero, could you tell more about the problem you solved by switching implementation? I agree on the "use list instead of arraylist, so you know there is a specific reason when using arraylist or linkedlist in the surrounding code" paradigm
Thorbjørn Ravn Andersen
+2  A: 

Yep, I use those as defaults. I generally have a rule that on public class methods, I always return the interface type (ie. Map, Set, List, etc.), since other classes (usually) don't need to know what the specific concrete class is. Inside class methods, I'll use the concrete type only if I need access to any extra methods it may have (or if it makes understanding the code easier), otherwise the interface is used.

It's good to be pretty flexible with any rules you do use, though, as a dependancy on concrete class visibility is something that can change over time (especially as your code gets more complex).

The Dissonant
A: 

I tend to use one of *Queue classes for queues. However LinkedList is a good choice if you don't need thread safety.

Peter Lawrey
+3  A: 

For some kind of lists (e.g. listeners) it makes sense to use a CopyOnWriteArrayList instead of a normal ArrayList. For almost everything else the basic implementations you mentioned are sufficient.

Bombe
The only reason to use CopyOnWriteArrayList is you want a thread safe implementation(without blocking), otherwise there is no difference between ArrayList and CopyOnWriteArrayList.
adrian.tarau
A: 

Using the interface type (List, Map) instead of the implementation type (ArrayList, HashMap) is irrelevant within methods - it's mainly important in public APIs, i.e. method signatures (and "public" doesn't necessarily mean "intended to be published outside your team).

When a method takes an ArrayList as a parameter, and you have something else, you're screwed and have to copy your data pointlessly. If the parameter type is List, callers are much more flexible and can, e.g. use Collections.EMPTY_LIST or Collections.singletonList().

Michael Borgwardt
+1  A: 

Indeed, always use base interfaces Collection, List, Map instead their implementations. To make thinkgs even more flexible you could hide your implementations behind static factory methods, which allow you to switch to a different implementation in case you find something better(I doubt there will be big changes in this field, but you never know). Another benefit is that the syntax is shorter thanks to generics.

Map<String, LongObjectClasName> map = CollectionUtils.newMap();

instead of 

Map<String, LongObjectClasName> map = new HashMap<String, LongObjectClasName>();


public class CollectionUtils {
.....

public <T> List<T> newList() {
        return new ArrayList<T>();
    }

    public <T> List<T> newList(int initialCapacity) {
        return new ArrayList<T>(initialCapacity);
    }

    public <T> List<T> newSynchronizedList() {
        return new Vector<T>();
    }

    public <T> List<T> newConcurrentList() {
        return new CopyOnWriteArrayList<T>();
    }

    public <T> List<T> newSynchronizedList(int initialCapacity) {
        return new Vector<T>(initialCapacity);
    }

...
}
adrian.tarau
Yeah, I have thought about doing something like this. Glad to know I'm not alone!
GreenieMeanie
+1  A: 

I don't really have a "default", though I suppose I use the implementations listed in the question more often than not. I think about what would be appropriate for whatever particular problem I'm working on, and use it. I don't just blindly default to using ArrayList, I put in 30 seconds of thought along the lines of "well, I'm going to be doing a lot of iterating and removing elements in the middle of this list so I should use a LinkedList".

And I almost always use the interface type for my reference, rather than the implementation. Remember that List is not the only interface that LinkedList implements. I see this a lot:

LinkedList<Item> queue = new LinkedList<Item>();

when what the programmer meant was:

Queue<Item> queue = new LinkedList<Item>();

I also use the Iterable interface a fair amount.

Adam Jaskiewicz
+1  A: 

If you are using LinkedList for a queue, you might consider using the Deque interface and ArrayDeque implementing class (introduced in Java 6) instead. To quote the Javadoc for ArrayDeque:

This class is likely to be faster than Stack when used as a stack, and faster than LinkedList when used as a queue.

markusk
A: 

I too typically use ArrayList, but I will use TreeSet or HashSet depending on the circumstances. When writing tests, however, Arrays.asList and Collections.singletonList are also frequently used. I've mostly been writing thread-local code, but I could also see using the various concurrent classes as well.

Also, there were times I used ArrayList when what I really wanted was a LinkedHashSet (before it was available).

Kathy Van Stone
I have used LinkedHashSet before also when I wanted the iterator to return in the order of insertion.
GreenieMeanie