I\'m sure there\'s a good reason, but could someone please explain why the java.util.Set
interface lacks get(int Index)
, or any similar get()
some data structures are missing from the standard java collections.
Bag (like set but can contain elements multiple times)
UniqueList (ordered list, can contain each element only once)
seems you would need a uniquelist in this case
if you need flexible data structures, you might be interested in Google Collections
This kind of leads to the question when you should use a set and when you should use a list. Usually, the advice goes:
A fourth case that appears often is that you need neither. In this case you see some programmers go with lists and some with sets. Personally I find it very harmful to see set as a list without ordering - because it is really a whole other beast. Unless you need stuff like set uniqueness or set equality, always favor lists.
If you don't mind the set to be sorted then you may be interested to take a look at the indexed-tree-map project.
The enhanced TreeSet/TreeMap provides access to elements by index or getting the index of an element. And the implementation is based on updating node weights in the RB tree. So no iteration or backing up by a list here.
Actually this is a recurring question when writing JavaEE applications which use Object-Relational Mapping (for example with Hibernate); and from all the people who replied here, Andreas Petersson is the only one who understood the real issue and offered the correct answer to it: Java is missing a UniqueList! (or you can also call it OrderedSet, or IndexedSet).
Maxwing mentioned this use-case (in which you need ordered AND unique data) and he suggested the SortedSet, but this is not what Marty Pitt really needed.
This "IndexedSet" is NOT the same as a SortedSet - in a SortedSet the elements are sorted by using a Comparator (or using their "natural" ordering).
But instead it is closer to a LinkedHashSet (which others also suggested), or even more so to an (also inexistent) "ArrayListSet", because it guarantees that the elements are returned in the same order as they were inserted.
But the LinkedHashSet is an implementation, not an interface! What is needed is an IndexedSet (or ListSet, or OrderedSet, or UniqueList) interface! This will allow the programmer to specify that he needs a collection of elements that have a specific order and without duplicates, and then instantiate it with any implementation (for example an implementation provided by Hibernate).
Since JDK is open-source, maybe this interface will be finally included in Java 7...
I'm not sure if anybody has spelled it out exactly this way, but you need to understand the following:
There is no "first" element in a set.
Because, as others have said, sets have no ordering. A set is a mathematical concept that specifically does not include ordering.
Of course, your computer can't really keep a list of stuff that's not ordered in memory. It has to have some ordering. Internally it's an array or a linked list or something. But you don't really know what it is, and it doesn't really have a first element; the element that comes out "first" comes out that way by chance, and might not be first next time. Even if you took steps to "guarantee" a particular first element, it's still coming out by chance, because you just happened to get it right for one particular implementation of a Set; a different implementation might not work that way with what you did. And, in fact, you may not know the implementation you're using as well as you think you do.
People run into this ALL. THE. TIME. with RDBMS systems and don't understand. An RDBMS query returns a set of records. This is the same type of set from mathematics: an unordered collection of items, only in this case the items are records. An RDBMS query result has no guaranteed order at all unless you use the ORDER BY clause, but all the time people assume it does and then trip themselves up some day when the shape of their data or code changes slightly and triggers the query optimizer to work a different way and suddenly the results don't come out in the order they expect. These are typically the people who didn't pay attention in database class (or when reading the documentation or tutorials) when it was explained to them, up front, that query results do not have a guaranteed ordering.
The reason why the Set interface doesn't have a get index-type call or even something even more basic, such as first() or last(), is because it is an ambiguous operation, and therefore a potentially dangerous operation. If a method returns a Set, and you call, say first() method on it, what is the expected result, given that the a generic Set makes no guarantees on the ordering? The resultant object could very well vary between each call of the method, or it might not and lull you into a false sense of security, until the library you're using changes changes the implementation underneath and now you find that all your code breaks for no particular reason.
The suggestions about workarounds listed here are good. If you need indexed access, use a list. Be careful with using iterators or toArray with a generic Set, because a) there is no guarantee on the ordering and b) there is no guarantee that the ordering will not change with subsequent invocations or with different underlying implementations. If you need something in between, a SortedSet or a LinkedHashSet is what you want.
// I do wish the Set interface had a get-random-element though.