«1. Обзор

В этом кратком руководстве мы представим различные методы инициализации HashSet со значениями во время его построения.

Если вместо этого вы хотите изучить возможности HashSet, обратитесь к этой основной статье здесь.

Мы рассмотрим встроенные методы Java начиная с Java 5 и ранее, а затем рассмотрим новый механизм, представленный начиная с Java 8. Мы также увидим пользовательский служебный метод и, наконец, изучим функции, предоставляемые сторонними библиотеками коллекций, Google Guava. особенно.

Если вам повезло, что вы уже перешли на JDK9+, вы можете просто использовать методы фабрики коллекций.

2. Встроенные методы Java

Давайте начнем с изучения трех встроенных механизмов, доступных начиная с Java 5 или ранее.

2.1. Использование другого экземпляра коллекции

Мы можем передать существующий экземпляр другой коллекции для инициализации набора. В приведенном ниже примере мы используем встроенный список:

Set<String> set = new HashSet<>(Arrays.asList("a", "b", "c"));

2.2. Использование анонимного класса

В еще одном подходе мы можем использовать анонимный класс для добавления элемента в HashSet.

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

Итак, в зависимости от того, как часто нам нужно инициализировать Set, мы можем попытаться избежать использования этого подхода:

Set<String> set = new HashSet<String>(){{
    add("a");
    add("b");
    add("c");
}};

2.3. Использование служебного метода Collections, начиная с Java 5

Вспомогательный класс Collections Java предоставляет метод с именем singleton для создания Set с одним элементом. Экземпляр Set, созданный с помощью метода singleton, является неизменяемым, что означает, что мы не можем добавлять к нему дополнительные значения.

Существуют ситуации, особенно при модульном тестировании, когда нам нужно создать набор с одним значением:

Set<String> set = Collections.singleton("a");

3. Определение пользовательского служебного метода

Мы можем определить статический окончательный метод, как показано ниже. Метод принимает переменные аргументы.

Использование Collections.addAll, которое принимает объект коллекции и массив значений, лучше всего из-за низких накладных расходов на копирование значений.

Метод использует дженерики, поэтому мы можем передавать значения любого типа:

public static final <T> Set<T> newHashSet(T... objs) {
    Set<T> set = new HashSet<T>();
    Collections.addAll(set, objs);
    return set;
}

В нашем коде можно использовать служебный метод, как показано ниже.

Set<String> set = newHashSet("a","b","c");

4. Использование Stream начиная с Java 8

С введением Stream API в Java 8 у нас появились дополнительные возможности. Мы можем использовать Stream with Collectors, как показано в коде ниже:

Set<String> set = Stream.of("a", "b", "c")
  .collect(Collectors.toCollection(HashSet::new));

5. Использование сторонней библиотеки коллекций

Существует несколько сторонних библиотек коллекций, включая Google Guava, Apache Commons Collections и Eclipse Collections, просто чтобы назвать немного.

Эти библиотеки предоставляют удобные служебные методы для инициализации коллекций, таких как Set. Поскольку Google Guava является одним из наиболее часто используемых здесь, у нас есть пример из него. В Guava есть удобные методы для изменяемых и неизменяемых объектов Set:

Set<String> set = Sets.newHashSet("a", "b", "c");

Точно так же в Guava есть служебный класс для создания неизменяемых экземпляров Set, как мы можем видеть в примере ниже.

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

6. Заключение

В заключение мы увидели несколько способов инициализации HashSet во время его создания. Эти подходы не обязательно охватывают все возможные способы. Это была просто попытка продемонстрировать наиболее распространенные способы.

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

Как всегда, рабочий пример кода доступен на GitHub.