3

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).

4

2 回答 2

3

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.

于 2013-01-04T15:33:46.303 回答
2

'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.

于 2013-01-04T15:22:26.220 回答