问题
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?
回答1:
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.
回答2:
Usually the reason is that they wanted to specify each function with a Big-O requirement and felt that getLast() could not be implemented efficiently on all lists. So they introduce it at each level with its Big-O promise.
Or it could just have been an oversight, or they felt it wasn't common enough and if you needed it you could get it with size/getIndex.
回答3:
An interface's goal is to provide the maximum usability with the lowest possible number of public methods. The less methods there are to support, the better. There is no getLast() method because this can be derived, as you said.
LinkedList, on the other hand is a concrete implementation, and therefore doesn't have these issues.
Edit: as Skaffman pointed out, this is not the main goal of an interface. It is more a secondary goal which allows implementations of this interface to be easier to maintain. The main purpose of an interface is to decouple the concrete implementation from the objects that use it.
回答4:
As you said, with List you can get the last one with getIndex(), since it's index based. So personally I do not see any good reason to put it (since you can write it yourself).
While a LinkedList is not array based, so no indexes, it makes sense to provide a method like that, sometimes you need to know the last item.
回答5:
The getLast() method is from the Deque interface that LinkedList implements. If you wanted an array backed version of that, you could use ArrayDeque . I guess it's not part of the List interface because they wanted to seperate out different abstract data types into seperate interfaces, even though an implementation like LinkedList can implement more than one interface.
回答6:
getLast() couldn't be implemented in a one-way linked list. getIndex() on a one-way linked list would probably scan the entire list from the beginning so it has an efficiency implication.
回答7:
The List interface doesn't have any convenience methods of that type. No getFirst() or getLast(). It is strictly index based. LinkedList needs a way of avoiding index based lookups if possible for performance reasons, so getLast is really an optimization, not a convenience method.
I'm sure the designers wanted to keep the amount of methods down, so they didn't add a lot of potentially convenient methods.
来源:https://stackoverflow.com/questions/1049518/why-does-the-java-list-interface-not-support-getlast