Существует ли .asSet (…) в каком-либо API?

110

Я ищу очень простой способ создать Сет.

Arrays.asList("a", "b" ...) создает List<String>

Есть что-нибудь подобное Set?

Cahen
источник
возможный дубликат Java - легко преобразовать массив в набор
Данило Пьяццалунга
1
это не так, создание набора и преобразование массива в набор - это не одно и то же
cahen

Ответы:

84

Теперь с Java 8 вы можете делать это без сторонней инфраструктуры:

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

См. Коллекционеры .

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

Г-н Андерсон
источник
4
В настоящее время с Java 8 это, вероятно, лучший ответ, потому что он не зависит от сторонних библиотек и может быть легко адаптирован к другим типам коллекций, поэтому я устанавливаю его как принятый. Большое спасибо всем за другие отличные решения. (кстати, этот сет изменяемый)
cahen 03
3
Теперь, кто сказал, что Java слишком многословна? Конечно, это лучший ответ!
BobDoolittle
Большое спасибо @BobDoolittle!
Мистер Андерсон
2
Для тех, кто использует java 9+, также см. Ответ Холли ниже: stackoverflow.com/a/48025159/229743
Тейлор
1
безупречный ответ, мистер Андерсон!
Гаурав
64

Используя Guava , это очень просто:

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

Или для изменяемого набора:

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

Дополнительные типы данных см. В руководстве пользователя Guava.

Михаэль Шмайсер
источник
Есть ли неизменяемая версия этого?
cahen
3
@cahen yes: Sets.newHashSet("a", "b")илиSets.newLinkedHashSet("a", "b")
Шон Патрик Флойд
1
Я добавил к ответу изменяемый вариант.
Михаэль Шмайсер
на самом деле Sets.newLinkedHashSet()не существует с этой подписью, извините
Шон Патрик Флойд
Мне удалось удалить один из аргументов типа:Set<String> mySet = ImmutableSet.of("a", "b");
joshden
55

Вы могли бы использовать

new HashSet<String>(Arrays.asList("a","b"));
Dev Blanked
источник
Я бы предпочел сделать это, а не использовать потоковую версию. Я могу просто статически импортировать "asList", делая его еще менее подробным.
Марсио Лукка
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.
Изменено
18

Как говорили другие, используйте:

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)

SetВнутри Arraysкласса нет реализации JDK «фиксированного размера» . а зачем тебе это? A Setгарантирует отсутствие дубликатов, но если вы набираете их вручную, вам не понадобится эта функциональность ... и Listесть больше методов. Оба интерфейса расширяются Collectionи Iterable.


Как говорили другие, используйте guava, если вам действительно нужна эта функциональность - поскольку ее нет в JDK. Посмотрите их ответы (в частности, ответ Михаэля Шмайсера), чтобы узнать об этом.

durron597
источник
3
На данный момент это лучший ответ, потому что он указывает на то, что на самом деле делает Arrays.asList (). Многие разработчики, похоже, считают, что Arrays.asList () создает java.util.ArrayList, в то время как на самом деле он создает java.util.Arrays $ ArrayList (который является лишь частично изменяемым и представляет собой живое представление базового массива)
Шон Патрик Флойд
1
Что касается того, почему кто-то захочет сделать это, наиболее распространенная причина для создания Set (или List) вручную - это тестовый класс, в который вы передаете тестовые значения.
Скотт Макинтайр
14

В Java 9 аналогичная функция была добавлена ​​с помощью фабричных методов:

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

(Есть и эквиваленты List.)

Холли Камминс
источник
Я попробовал это и получил предупреждение компилятора, что это не метод API.
Philippe Gioseffi
Вот соответствующий java-документ: docs.oracle.com/javase/9/docs/api/java/util/Set.html . Помимо использования Java 9+ JDK, вам может потребоваться настроить вашу среду IDE или инструмент сборки для использования совместимости с Java 9 (например, для maven это будут те же шаги, что и здесь, но установлено значение 1.9: stackoverflow.com/ вопросы / 16798066 /… )
Холли Камминс
Хотелось бы использовать Java 9 .. Мы живем в прошлом! :(
jDub9
это хорошо, но с некоторыми ограничениями по размеру аргументов ...
Радослав Иванов
3

Нет, но ты можешь сделать это вот так

new HashSet<String>(Arrays.asList("a", "b", ...));
Евгений Дорофеев
источник
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 ...) .

Филипп Джозеффи
источник