Java Set сохранить порядок?

179

Сохраняет ли Java-набор порядок? Метод возвращает мне Set, и, предположительно, данные упорядочены, но итерируя по Set, данные неупорядочены. Есть ли лучший способ справиться с этим? Нужно ли менять метод, чтобы он возвращал что-то отличное от Set?

user840930
источник
3
«Элементы возвращаются в произвольном порядке (если этот набор не является экземпляром некоторого класса, который предоставляет гарантию)». это то, что говорит метод итератора для набора. нашел здесь
keyser

Ответы:

257

SetИнтерфейс не дает никаких гарантий заказа.

Его подчиненный интерфейс SortedSetпредставляет собой набор, отсортированный по некоторому критерию. В Java 6 есть два стандартных контейнера, которые реализуют SortedSet. Они есть TreeSetи ConcurrentSkipListSet.

Помимо SortedSetинтерфейса есть еще и LinkedHashSetкласс. Он запоминает порядок, в котором элементы были вставлены в набор, и возвращает его элементы в этом порядке.

NPE
источник
21
Кроме того, из-за разного хеширования строк в Java 8, порядок по умолчанию (несортированный) в наборах и картах будет меняться. Если вы полагаетесь на несортированный порядок, ваш код будет работать по-другому в Java 8.
rustyx
Я понимаю, что класс, не упорядочивающий, является нормальным, но я ожидал, что поведение будет оставлять их, как они были представлены, и не связываться с порядком, а просто перетасовывать элементы каждый раз при агрегировании. Ваше решение не является оптимальным, потому что тогда мне придется реализовать целую структуру, чтобы они были отсортированы ЖЕ ВРЕМЯ, как они были представлены: S
White_King
@White_King: набор - это математическая концепция, которая не содержит понятия «порядок вставки», поэтому имеет смысл для интерфейса Java следовать его соглашениям. Существуют упорядоченные множества, но порядок определяется отношением (компаратор в Java), снова сопоставляя определение в теории множеств с определением в Java. Вы ожидаете, что он сохранит порядок вставки, вероятно, из списков, но наборы не являются списками.
Конрад
103

LinkedHashSet - это то, что вам нужно.

xiaofeng.li
источник
43
А Listне является Set(это не гарантирует уникальность членства).
Ограниченное искупление
10
Во многих бизнес-уникальных случаях List нельзя использовать просто для сохранения порядка вместо Set. LinkedHashSet поддерживает порядок и хранит уникальные.
Губы
18

Поскольку многие из участников предложили использовать LinkedHashSet, чтобы сохранить порядок коллекции. Вы можете обернуть ваш набор с помощью этой реализации.

Реализация SortedSet может использоваться для сортированного порядка, но для вашей цели используйте LinkedHashSet .

Также из документов,

«Эта реализация избавляет своих клиентов от неуказанного, обычно хаотического порядка, предоставляемого HashSet, без увеличения стоимости, связанного с TreeSet. Его можно использовать для создания копии набора, который имеет тот же порядок, что и оригинал, независимо от оригинала реализация набора: "

Источник: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html

Lakshman
источник
9

Набор это просто интерфейс. Чтобы сохранить порядок, вы должны использовать конкретную реализацию этого интерфейса и подчиненного интерфейса SortedSet, например TreeSet или LinkedHashSet. Вы можете обернуть ваш набор следующим образом:

Set myOrderedSet = new LinkedHashSet(mySet);
javatutorial
источник
7

Вот краткий обзор характеристик порядка стандартных Setреализаций, доступных в Java:

  1. сохранить порядок вставки: LinkedHashSet и CopyOnWriteArraySet (токарно-сейф)
  2. сохраняйте отсортированные элементы в наборе: TreeSet , EnumSet (специфично для перечислений) и ConcurrentSkipListSet (поточно- ориентированный )
  3. не хранит элементы в каком-либо определенном порядке: HashSet (тот, который вы пробовали)

Для вашего конкретного случая вы можете сначала отсортировать элементы, а затем использовать любой из 1 или 2 (наиболее вероятно, LinkedHashSetили TreeSet). Или, альтернативно и более эффективно , вы можете просто добавить несортированные данные в папку, TreeSetкоторая автоматически позаботится о сортировке.

assylias
источник
7

Для сохранения заказа используйте Listили LinkedHashSet.

JHS
источник
1
Это LinkedHashSetне ... Map.
Марко Топольник
Мне нужен набор, а не список, мне нужен набор, который ТАКЖЕ сохраняет порядок инъекции объектов, которые я предполагаю
White_King
5

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

Данаил Цветанов
источник
3

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

Возвращает итератор для элементов в этом наборе. Элементы возвращаются в произвольном порядке (если этот набор не является экземпляром некоторого класса, который предоставляет гарантию).

И, как уже заявлено shuuchan , a TreeSetявляется реализацией, Setкоторая имеет гарантированный порядок:

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

hmjd
источник
3

Обычно установленный не сохраняет порядок, такой как HashSet, чтобы быстро найти изумруд, но вы можете попробовать LinkedHashSet, он сохранит порядок, в который вы положили.

user1335794
источник
1

Есть 2 разные вещи.

  1. Сортировка элементов в наборе. Для которого у нас есть SortedSet и аналогичные реализации.
  2. Поддерживать порядок вставки в наборе. Для чего могут быть использованы LinkedHashSet и CopyOnWriteArraySet (потокобезопасный).
Аруна
источник
0

Сам интерфейс Set не предусматривает какого-либо конкретного порядка. SortedSet делает однако.

Йенс Боргланд
источник
-2

Только SortedSetможет сделать заказSet


источник
Вопрос в том, чтобы сохранить порядок вставки (который сортируется).
assylias