Является ли набор "toArray" детерминированным? - PullRequest
6 голосов
/ 31 марта 2012

Очевидно, что наборы не имеют какого-либо порядка, поэтому я не могу ожидать какого-либо конкретного порядка, если я делаю

String[] string = mySet.toArray();

Однако я столкнулся со случаем использования, когда мне все равно, в каком порядке расположен массив строк, но мне НУЖНО, чтобы это было так, если два набора равны друг другу, то:

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

будет выдавать одну и ту же строку для этих наборов всегда, независимо от того, сколько раз я запускаю программу, если я придерживаюсь одного и того же кода.

Есть ли у меня эта гарантия?

Аналогично, верно ли все это для порядка, в котором элементы появляются для данного набора в итераторе?

Ответы [ 6 ]

7 голосов
/ 31 марта 2012

Как правило, вы не можете гарантировать порядок Set, как вы упомянули, поэтому, даже если он работает сейчас, он может не работать в будущем. Тем не менее, вы можете гарантировать порядок LinkedHashSet, так что вы можете просто использовать это. Это работает, только если в наборах элементы были вставлены в том же порядке. Если у вас нет такой ситуации, вам, вероятно, нужно просто отсортировать набор и распечатать его.

4 голосов
/ 31 марта 2012

Технически, нет, у вас нет гарантии. Set - это интерфейс. Реализации могут отличаться и могут соответствовать или не соответствовать этому требованию.

Принудительно решить проблему, самостоятельно отсортировав массив после извлечения результатов из набора.

4 голосов
/ 31 марта 2012

Нет, абсолютно нет. Для тривиального примера рассмотрим:

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

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

Эти два набора равны, но поскольку LinkedHashSet сохраняет порядок вставки, гарантируется, что их итераторы будут возвращать значения в другом порядке - и я ожидаю, что toArray будет иметь тот же эффект.

3 голосов
/ 31 марта 2012

Это будет полностью зависеть от реализации Set. Set - это интерфейс, а не класс, и toArray() не гарантирует ничего, кроме того, что он должен соответствовать Итератору реализации.

Из Javadoc для Set.toArray ():

Если этот набор дает какие-либо гарантии относительно того, в каком порядке его элементы возвращаются его итератором, этот метод должен возвращать элементы в том же порядке.

2 голосов
/ 31 марта 2012

У вас нет этой гарантии. Может случиться так, что вы всегда будете видеть эту работу, потому что я подозреваю, что большинство реализаций Set.toArray() будет производить одинаковый порядок для равных наборов, но вы не можете полагаться на это.

Вы также не можете рассчитывать на заказ от итератора.

Наборы полностью и полностью неупорядочены. Из-за поведения реализации вы можете получить из них нечто, похожее на последовательный порядок, но на это никоим образом нельзя полагаться.

1 голос
/ 31 марта 2012

Для HashSet вы можете добавлять элементы в одном и том же порядке и получать разные заказы в зависимости от емкости и коэффициента загрузки.

Вот пример, где вы можете иметь много разных заказов из одной коллекции.

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

...