Чи існує .asSet (…) в будь-якому API?


108

Я шукаю дуже простий спосіб створити набір.

Arrays.asList("a", "b" ...) створює а List<String>

Чи є щось подібне Set?



1
це не так, створити набір і перетворити масив у набір - це не одне і те ж
cahen

Відповіді:


84

Тепер з Java 8 ви можете це зробити без необхідності сторонніх фреймворків:

Set<String> set = Stream.of("a","b","c").collect(Collectors.toSet());

Див. Колекціонери .

Насолоджуйтесь!


4
На сьогоднішній день з Java 8 це, мабуть, найкраща відповідь, оскільки це не залежить від сторонніх бібліотек і може бути легко адаптоване до інших типів колекцій, тому я встановлюю це як прийняте. Велике спасибі всім за інші чудові рішення. (btw, цей набір є
змінним

3
Тепер, хто сказав, що Java занадто багатослівний? Звичайно, це найкраща відповідь!
BobDoolittle

Дякую чимало @BobDoolittle!
Містер Андерсон

2
Для тих, хто використовує java 9+, будь ласка, дивіться відповідь Холлі нижче: stackoverflow.com/a/48025159/229743
Тейлор

1
бездоганна відповідь містер Андерсон!
gaurav

63

Використовуючи Guava , це так просто:

Set<String> mySet = ImmutableSet.<String> of("a", "b");

Або для змінного набору:

Set<String> mySet = Sets.newHashSet("a", "b")

Більше типів даних див. У посібнику користувача Guava


Чи існує неперемінна версія цього?
cahen

3
@cahen так: Sets.newHashSet("a", "b")абоSets.newLinkedHashSet("a", "b")
Шон Патрік Флойд

1
Я додав у відповідь змінний варіант.
Michael Schmeißer

насправді Sets.newLinkedHashSet()не існує з цим підписом, вибачте
Шон Патрік Флойд

Мені вдалося видалити один із аргументів типу:Set<String> mySet = ImmutableSet.of("a", "b");
joshden


24

Для особливих випадків множин з нулем або одним членом ви можете використовувати:

java.util.Collections.EMPTY_SET

і:

java.util.Collections.singleton("A")

для цих особливих випадків це, мабуть, найкраще рішення, оскільки він використовує стандартний API java.util
arcuri82

2
java.util.Collections.emptySet()на мій погляд, перевагу перед EMPTY_SET, завдяки безпеці типу. З коментарів до класу Колекції:Unlike the like-named field, this method is parameterized.
Відредаговано

17

Як уже говорили інші, використовуйте:

new HashSet<String>(Arrays.asList("a","b"));

Причина цього зовсім НЕ існує в Java є те , що Arrays.asListповертає список фіксованого розміру, іншими словами:

public static void main(String a[])
{
  List<String> myList = Arrays.asList("a", "b");
  myList.add("c");
}

Повернення:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(Unknown Source)
    at java.util.AbstractList.add(Unknown Source)

В JDK не існує реалізації "фіксованого розміру" Setвсередині Arraysкласу. Чому ти цього хочеш? А Setгарантія , що не існує ніяких дублікатів, але якщо ви набираєте їх вручну, ви не повинні , що функціональність ... і Listє кілька методів. Обидва інтерфейси поширюються Collectionі Iterable.


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


3
Це найкраща відповідь поки що, оскільки вона вказує на те, що насправді робить Arrays.asList (). Здається, багато розробників вважають, що Arrays.asList () створює java.util.ArrayList, в той час як він фактично створює java.util.Arrays $ ArrayList (який лише частково змінюється і живе вигляд основного масиву)
Шон Патрік Флойд

1
Щодо того, чому хтось хотів би це зробити, найпоширеніша причина побудови набору (або списку) вручну знаходиться в тестовому класі, де ви передаєте тестові значення.
Скотт Макінтайр

14

У Java 9 подібна функція була додана за допомогою заводських методів:

Set<String> oneLinerSet = Set.of("a", "b", ...);

(Є і їх еквіваленти List.)


Я спробував це і отримав попередження компілятора, що це не метод API.
Філіп Джозеффі

Ось відповідний java doc: docs.oracle.com/javase/9/docs/api/java/util/Set.html . Окрім використання JDK Java 9+, можливо, вам знадобиться налаштувати свій IDE або створити інструмент для використання відповідності Java 9 (наприклад, для maven, це будуть схожі кроки з описаними тут, але встановлено на 1.9: stackoverflow.com/ питання / 16798066 /… )
Холлі Куммінс

Хочемо, щоб ми могли використовувати Java 9 .. Ми живемо в минулому! :(
jDub9

це добре, але є деякі обмеження щодо розміру аргументів ...
Радослав Іванов



2

Ось невеликий метод, який ви можете використовувати

  /**
   * Utility method analogous to {@link java.util.Arrays#asList(Object[])}
   *
   * @param ts
   * @param <T>
   * @return the set of all the parameters given.
   */
  @SafeVarargs
  @SuppressWarnings("varargs")
  public static <T> Set<T> asSet(T... ts) {
    return new HashSet<>(Arrays.asList(ts));
  }

1

Ще один спосіб зробити це за допомогою Java 8 та переліків:

Set<String> set = EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.READ);

Дивіться EnumSet .

Я рекомендую аналіз ефективності між цим підходом та

Set<String> set = Stream.of(StandardOpenOption.CREATE, StandardOpenOption.READ).collect(Collectors.toSet());

тому що якщо у вас є більше п'яти елементів, javadoc методу заявляє, що це можуть бути проблеми з продуктивністю, як ви можете бачити в javadoc Set.Of (E, E ...) .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.