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


179

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


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

Ответы:


257

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

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

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


21
Кроме того, из-за разного хеширования строк в Java 8, порядок по умолчанию (несортированный) в наборах и картах будет меняться. Если вы полагаетесь на несортированный порядок, ваш код будет работать по-другому в Java 8.
rustyx

Я понимаю, что класс, не упорядочивающий, является нормальным, но я ожидал, что поведение будет оставлять их, как они были представлены, и не связываться с порядком, а просто перетасовывать элементы каждый раз при агрегировании. Ваше решение не является оптимальным, потому что тогда мне придется реализовать целую структуру, чтобы они были отсортированы ЖЕ ВРЕМЯ, как они были представлены: S
White_King

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

103

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


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


9

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

Set myOrderedSet = new LinkedHashSet(mySet);

7

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

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

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


7

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


1
Это LinkedHashSetне ... Map.
Марко Топольник

Мне нужен набор, а не список, мне нужен набор, который ТАКЖЕ сохраняет порядок инъекции объектов, которые я предполагаю
White_King

5

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


3

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

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

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

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


3

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


1

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

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



-2

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


Вопрос в том, чтобы сохранить порядок вставки (который сортируется).
assylias
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.