Java Set retain order?
Asked Answered
J

14

246

Does a Java Set retain order? A method is returning a Set to me and supposedly the data is ordered but iterating over the Set, the data is unordered. Is there a better way to manage this? Does the method need to be changed to return something other than a Set?

Johnniejohnny answered 25/5, 2012 at 10:27 Comment(1)
"The elements are returned in no particular order (unless this set is an instance of some class that provides a guarantee)." is what the iterator method for a set says. found hereAltheta
A
363

The Set interface does not provide any ordering guarantees.

Its sub-interface SortedSet, and later NavigableSet, represents a set that is sorted according to some criterion. In Java 6, there are two standard containers that implement SortedSet. They are TreeSet and ConcurrentSkipListSet.

In addition to the SortedSet/NavigableSet interfaces, there is also the LinkedHashSet class. It remembers the order in which the elements were inserted into the set, and returns its elements in that order.

In Java 21+, with sequenced collections added, we have the super-interface of SequencedSet to cover all three of those mentioned classes: ConcurrentSkipListSet, LinkedHashSet, TreeSet.

Aesthesia answered 25/5, 2012 at 10:30 Comment(4)
Furthermore, due to the different String hashing in Java 8, the default (unsorted) ordering in Sets and Maps will change. If you rely on unsorted ordering, your code will behave differently under Java 8.Chiefly
I get that the class not ordering is normal, but the behavior I was expecting was to leave them as they were introduced and not mess with the order, instead it is just shuffling the elements each time one is aggregated. Your solution is not optimal wither because then I will have to implement a whole structure for them to be sorted THE SAME WAY they were introduced :SCollectivism
@White_King: A set is a mathematical concept that does not contain the notion of "insertion order" so it makes sense for the Java interface to follow its conventions. There are ordered sets but the order is specified by a relation (comparator in Java), again matching the definition in set theory with the definition in Java. Your expectation of it keeping insertion order probably comes from lists but sets are not lists.Menstruate
As of Java 21, both SortedSet and LinkedHashSet extend/implement SequencedSet, which represents a reversible set with a well-defined element encounter order: https://mcmap.net/q/116136/-java-set-retain-order.Cleanlimbed
A
148

LinkedHashSet is what you need, as it is a Set with a well-defined encounter order.

If the item uniqueness constraint isn't necessary, you could alternatively use a List instead of a Set.

Ascension answered 25/5, 2012 at 10:29 Comment(2)
A List is not a Set (it doesn't guarantee uniqueness of membership).Ashwell
In many business unique cases List can't be used just to retain order instead of Set. LinkedHashSet maintains order and stores unique.Coyote
P
19

As many of the members suggested use LinkedHashSet to retain the order of the collection. U can wrap your set using this implementation.

SortedSet implementation can be used for sorted order but for your purpose use LinkedHashSet.

Also from the docs,

"This implementation spares its clients from the unspecified, generally chaotic ordering provided by HashSet, without incurring the increased cost associated with TreeSet. It can be used to produce a copy of a set that has the same order as the original, regardless of the original set's implementation:"

Source : http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html

Participation answered 7/12, 2012 at 7:30 Comment(0)
D
18

Set is just an interface. In order to retain order, you have to use a specific implementation of that interface and the sub-interface SortedSet, for example TreeSet or LinkedHashSet. You can wrap your Set this way:

Set myOrderedSet = new LinkedHashSet(mySet);
Dorchester answered 25/5, 2012 at 10:29 Comment(0)
V
8

To retain the order use List or a LinkedHashSet.

Vexed answered 25/5, 2012 at 10:31 Comment(2)
It's LinkedHashSet, not ...Map.Petronel
I need a Set not a List, I need a Set that ALSO retains the order of injection of the objects I guessCollectivism
I
8

A LinkedHashSet is an ordered version of HashSet that maintains a doubly-linked List across all elements. Use this class instead of HashSet when you care about the iteration order.

Inactive answered 4/4, 2018 at 11:58 Comment(0)
J
7

Here is a quick summary of the order characteristics of the standard Set implementations available in Java:

  1. keep the insertion order: LinkedHashSet and CopyOnWriteArraySet (thread-safe)
  2. keep the items sorted within the set: TreeSet, EnumSet (specific to enums) and ConcurrentSkipListSet (thread-safe)
  3. does not keep the items in any specific order: HashSet (the one you tried)

For your specific case, you can either sort the items first and then use any of 1 or 2 (most likely LinkedHashSet or TreeSet). Or alternatively and more efficiently, you can just add unsorted data to a TreeSet which will take care of the sorting automatically for you.

Jellify answered 25/5, 2012 at 10:36 Comment(0)
R
3

From the javadoc for Set.iterator():

Returns an iterator over the elements in this set. The elements are returned in no particular order (unless this set is an instance of some class that provides a guarantee).

And, as already stated by shuuchan, a TreeSet is an implemention of Set that has a guaranteed order:

The elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.

Robichaud answered 25/5, 2012 at 10:30 Comment(0)
S
3

Normally set does not keep the order, such as HashSet in order to quickly find a emelent, but you can try LinkedHashSet it will keep the order which you put in.

Schell answered 25/5, 2012 at 10:30 Comment(0)
F
1

There are 2 different things.

  1. Sort the elements in a set. For which we have SortedSet and similar implementations.
  2. Maintain insertion order in a set. For which LinkedHashSet and CopyOnWriteArraySet (thread-safe) can be used.
Filum answered 2/10, 2019 at 15:44 Comment(0)
C
1

An implementation of interface SequencedSet (introduced in Java 21) can be used when both encounter order and Set semantics (e.g. element uniqueness) are important.

The Set interface does not require a well-defined encounter order, a fact which is explicitly called out in the Javadocs for its iterator method:

Returns an iterator over the elements in this set. The elements are returned in no particular order (unless this set is an instance of some class that provides a guarantee).

The SequencedSet interface is a subinterface of Set that also requires that the implementation have a well-defined encounter order. Both LinkedHashSet and SortedSet implement/extend this new interface.

Cleanlimbed answered 12/6, 2023 at 20:49 Comment(0)
D
0

The Set interface itself does not stipulate any particular order. The SortedSet does however.

Dunant answered 25/5, 2012 at 10:30 Comment(0)
F
0

Iterator returned by Set is not suppose to return data in Ordered way. See this Two java.util.Iterators to the same collection: do they have to return elements in the same order?

Falster answered 25/5, 2012 at 10:31 Comment(0)
M
-2

Only SortedSet can do the ordering of the Set

Mucoid answered 25/5, 2012 at 10:33 Comment(1)
The question is about retaining the insertion order (which happens to be sorted).Jellify

© 2022 - 2024 — McMap. All rights reserved.