Java Set зберігає замовлення?


179

Чи зберігає набір Java комплект? Метод повертає мені набір, і нібито дані впорядковані, але повторюються над набором, дані не упорядковані. Чи є кращий спосіб управління цим? Чи потрібно змінювати метод, щоб повернути щось, крім набору?


3
"Елементи не повертаються в конкретному порядку (якщо тільки цей набір не є екземпляром якогось класу, який забезпечує гарантію)." це те, що говорить метод ітератора для набору. знайдено тут
клавішник

Відповіді:


256

SetІнтерфейс не дає ніяких гарантій замовлення.

Його підінтерфейс SortedSetявляє собою набір, який сортується за деяким критерієм. У Java 6 є два стандартні контейнери, які реалізують SortedSet. Вони є TreeSetі ConcurrentSkipListSet.

Окрім SortedSetінтерфейсу, є ще й LinkedHashSetклас. Він запам'ятовує порядок, в якому елементи були вставлені в набір, і повертає його елементи в тому порядку.


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

Я розумію, що клас, який не впорядковує, є нормальним, але поведінка, яку я очікував, - це залишити їх, коли вони були представлені, і не возитися з порядком, натомість він просто перетасовує елементи щоразу, коли один агрегується. Ваше рішення не є оптимальним, оскільки тоді мені доведеться реалізувати цілу структуру для того, щоб вони були
сортовані

@White_King: Набір - це математичне поняття, яке не містить поняття "порядок вставки", тому має сенс інтерфейс Java слідувати його умовам. Існують впорядковані набори, але порядок визначається співвідношенням (порівняльник у Java), що знову відповідає визначенню в теорії множин та визначенню в Java. Ви сподіваєтесь, що він буде виконувати порядок вставки, мабуть, виходить зі списків, але набори - не списки.
Konrad Höffner

103

LinkedHashSet - те, що вам потрібно.


43
А Listне є Set(це не гарантує унікальність членства).
Обмежене спокута

10
У багатьох унікальних бізнес-випадках Список не може використовуватися лише для збереження порядку замість Установити. 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.