Reputation: 16932
I have a code in which for-each-loops on a Set need to rely on the fact that the iterator returns the elements always in the same order, e.g.
for(ParameterObject parameter : parameters) {
/* ... */
}
The iterators returned by HashSet
are not guaranteed to have this property, however it is documented that the iterators of LinkedHashSet
do have this property. So my code uses a LinkedHashSet
and everything works fine.
However, I am wondering if I could endow the my code with a check that the set passed to it conforms to the requirement. It appears as if this is not possible (except of a direct test on LinkedHashSet
). There is no interface implemented by LinkedHashSet
which I could test on and there is no interface implemented by LinkedHashSet.iterator()
which I could test on. It would be nice if there is an interface like OrderConsistentCollection
or OrderConsistentIterator
.
(I need this property here).
Upvotes: 3
Views: 3113
Reputation: 43391
There isn't a way you can check for it -- but you can ensure it anyway, by simply copying the set into a collection that does have that property. A LinkedHashSet
would do the trick, but if all you need is the iteration, an ArrayList
would probably serve you better.
List<Foo> parameters = new ArrayList<>(parametersSet);
Now parameters
will always return an iterator with the same ordering.
That said, you'd probably be fine with Evgeniy Dorofeev's suggestion, which points out that even the sets that don't guarantee a particular ordering usually do have a stable ordering (even if they don't guarantee it). HashSet
acts that way, for instance. You'd actually have to have a pretty funky set, or take active randomization measures, to not have a stable ordering.
HashSet
's ordering is not guaranteed, but it depends on the hash codes of its elements as well as the order in which they were inserted; they don't want to guarantee anything because they don't want to lock themselves into any one strategy, and even this loose of a contract would make for essentially random order if the objects' hash codes came from Object.hashCode()
. Rather than specifying an ordering with complex implications, and then saying it's subject to change, they just said there's no guarantees. But those are the two factors for ordering, and if the set isn't being modified, then those two factors are going to be stable from one iteration to the next.
Upvotes: 3
Reputation: 136062
'HashSet.iterator does not return in any particular order' means that the elements returned by iterator are not sorted or ordered like in List or LinkedHashSet. But the HashSet.iterator will always return the elements in one and the same order while the HashSet is the same.
HashSet iterator is actually predictable, see this
HashSet set = new HashSet();
set.add(9);
set.add(2);
set.add(5);
set.add(1);
System.out.println(set);
I can foretell the output, it will be 1, 2, 5, 9. Because the elements kind of sorted by hashCode.
Upvotes: 3