Search code examples
javacollections

Why does the Java List interface not support getLast()?


I'm trying to understand the API inconsistency in the Java standard collections library.

There is no method in List or in AbstractList to get the last item, although one can simulate that with size and getIndex().

However, LinkedList supports that function.

Any idea why it was decided not to support this method in the interface?


Solution

  • The java.util.List interface doesn't support getLast() because the designers went for a 'minimal interface'. With the minimal number of methods defined it makes it both easier to understand and quicker to learn.

    This is in contrast with a 'humane interface' (such as used in the Ruby array class) which attempts to provide methods for doing common operations (e.g. getLast()). As there are many uses which such a fundamental concept as a list can be put to this tends to lead to much larger interfaces.

    For further information see Martin Fowler's Minimal Interface and Humane Interface descriptions.

    As to why LinkedList supports getLast() etc., to quote the javadoc:

    ... the LinkedList class provides uniformly named methods to get, remove and insert an element at the beginning and end of the list. These operations allow linked lists to be used as a stack, queue, or double-ended queue (deque).

    Presumably it was felt that a general List would not be adequate for these specific use cases.

    As an insight into the mind of the principal designer of the Java Collections API (Joshua Bloch) he provides this list of API design maxims by which he works. Of which, the most pertinent to this question are:

    Early drafts of APIs should be short, typically one page with class and method signatures and one-line descriptions. This makes it easy to restructure the API when you don't get it right the first time.

    When in doubt, leave it out. If there is a fundamental theorem of API design, this is it. It applies equally to functionality, classes, methods, and parameters. Every facet of an API should be as small as possible, but no smaller. You can always add things later, but you can't take them away. Minimizing conceptual weight is more important than class- or method-count.

    Keep APIs free of implementations details. They confuse users and inhibit the flexibility to evolve. It isn't always obvious what's an implementation detail: Be wary of overspecification.

    Minimize accessibility; when in doubt, make it private. This simplifies APIs and reduces coupling.

    Consider the performance consequences of API design decisions, but don't warp an API to achieve performance gains. Luckily, good APIs typically lend themselves to fast implementations.

    However he also states:

    Don't make the client do anything the library could do. Violating this rule leads to boilerplate code in the client, which is annoying and error-prone.

    Which just shows that design guidelines often conflict and the hardest part of an API designers job is to balance these conflicts.