Wayne
Wayne

Reputation: 984

Is there a way to create a List/Set which keeps insertion order and does not allow duplicates in Java?

What is the most efficient way of maintaining a list that does not allow duplicates, but maintains insertion order and also allows the retrieval of the last inserted element in Java?

Upvotes: 4

Views: 5589

Answers (3)

Thomas
Thomas

Reputation: 88757

Try LinkedHashSet, which keeps the order of input.

Note that re-inserting an element would update its position in the input order, thus you might first try and check whether the element is already contained in the set.

Edit:

You could also try the Apache commons collections class ListOrderedSet which according to the JavaDoc (if I didn't missread anything again :) ) would decorate a set in order to keep insertion order and provides a get(index) method.

Thus, it seems you can get what you want by using new ListOrderedSet(new HashSet());

Unfortunately this class doesn't provide a generic parameter, but it might get you started.

Edit 2:

Here's a project that seems to represent commons collections with generics, i.e. it has a ListOrderedSet<E> and thus you could for example call new ListOrderedSet<String>(new HashSet<String>());

Upvotes: 10

Tom Anderson
Tom Anderson

Reputation: 47253

I don't think there's anything in the JDK which does this.

However, LinkedHashMap, which is used as the basis for LinkedHashSet, comes close: it maintains a circular doubly-linked list of the entries in the map. It only tracks the head of the list not the tail, but because the list is circular, header.before is the tail (the most recently inserted element).

You could therefore implement what you need on top of this. LinkedHashMap has not been designed for extension, so this is somewhat awkward. You could copy the code into your own class and add a suitable last() method (be aware of licensing issues here), or you could extend the existing class, and add a method which uses reflection to get at the private header and before fields.

That would get you a Map, rather than a Set. However, HashSet is already a wrapper which makes a Map look like a Set. Again, it is not designed for general extension, but you could write a subclass whose constructor calls the super constructor, then uses more reflection to replace the superclass's value of map with an instance of your new map. From there on, the class should do exactly what you want.

As an aside, the library classes here were all written by Josh Bloch and Neal Gafter. Those guys are two of the giants of Java. And yet the code in there is largely horrible. Never meet your heroes.

Upvotes: 0

Jakob Alexander Eichler
Jakob Alexander Eichler

Reputation: 3056

Just use a TreeSet.

Upvotes: -1

Related Questions