Is a set's “toArray” deterministic?

2019-06-19 12:40发布

问题:

Obviously, sets do not have any kind of ordering, so I cannot expect any specific ordering if I do

String[] string = mySet.toArray();

However, I am faced with a use case where I don't care what ordering the string array is in, but I DO need it to be the case that if two sets are equal to each other, then:

StringUtils.join(mySet.toArray(),',');

will produce the same exact string for those sets, always, no matter how many times I run the program assuming I stick with the same code.

Do I have this guarantee?

Similarly, does this whole true for the order that elements appear for a given Set in an iterator?

回答1:

Technically, no you don't have a guarantee. Set is an Interface. Implementations will vary and may or may not obey this requirement.

Force the issue by sorting the array yourself after extracting the results from the Set.



回答2:

In general, you cannot guarantee the order of a Set as you mention, so even if it does work now, it may not in the future. However, you can guarantee the order of a LinkedHashSet so you can just use that. This only works if the sets had the elements inserted in the same order though. If you don't have that situation, you probably just have to sort the set and print it.



回答3:

No, absolutely not. For a trivial example, consider:

 LinkedHashSet<String> set1 = new LinkedHashSet<String>();
 set1.add("x");
 set1.add("y");

 LinkedHashSet<String> set2 = new LinkedHashSet<String>();
 set2.add("y");
 set2.add("x");

Those two sets are equal, but because LinkedHashSet preserves insertion order, it's guaranteed that their iterators will return values in a different order - and I'd expect toArray to have the same effect.



回答4:

That would be completely dependent on the Set implementation. Set is an interface, not a class, and toArray() does not guarantee anything except that it must match the implementation's Iterator.

From the javadoc for Set.toArray():

If this set makes any guarantees as to what order its elements are returned by its iterator, this method must return the elements in the same order.



回答5:

You do not have this guarantee. It may be that you will always see this work, because I suspect most implementations of Set.toArray() will produce the same ordering for equal sets, but you cannot rely on this.

Nor can you rely on the order from an iterator.

Sets are completely and wholly unordered. You might, due to implementation behaviour, get something that looks like a consistent order out of them, but this is not in any way to be relied upon.



回答6:

For HashSet you can add element in the same order and get different orders based on the capacity and load factor.

Here is an example where you can have many different orders from the same collection.

http://vanillajava.blogspot.co.uk/2011/09/order-of-elements-in-hash-collection.html