Как инициализировать значения HashSet по построению? - PullRequest
651 голосов
/ 11 января 2010

Мне нужно создать Set с начальными значениями.

Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");

Есть ли способ сделать это в одной строке кода? Например, это полезно для окончательного статического поля.

Ответы [ 23 ]

14 голосов
/ 30 августа 2010

Обобщение вспомогательной функции * * * * * ответа coobird для создания новых HashSet s:

public static <T> Set<T> newHashSet(T... objs) {
    Set<T> set = new HashSet<T>();
    for (T o : objs) {
        set.add(o);
    }
    return set;
}
11 голосов
/ 23 декабря 2015

Если содержащийся тип набора является перечислением, то существует фабричный метод, созданный Java (начиная с 1.5):

Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... );
5 голосов
/ 14 июля 2017
import com.google.common.collect.Sets;
Sets.newHashSet("a", "b");

или

import com.google.common.collect.ImmutableSet;
ImmutableSet.of("a", "b");
5 голосов
/ 29 февраля 2016

С Eclipse Collections существует несколько различных способов инициализации Set, содержащих символы «a» и «b» в одном операторе. В коллекциях Eclipse есть контейнеры как для объектных, так и для примитивных типов, поэтому я проиллюстрировал, как можно использовать Set<String> или CharSet в дополнение к изменяемым, неизменным, синхронизированным и неизменяемым версиям обоих.

Set<String> set =
    Sets.mutable.with("a", "b");
HashSet<String> hashSet =
    Sets.mutable.with("a", "b").asLazy().into(new HashSet<String>());
Set<String> synchronizedSet =
    Sets.mutable.with("a", "b").asSynchronized();
Set<String> unmodifiableSet =
    Sets.mutable.with("a", "b").asUnmodifiable();

MutableSet<String> mutableSet =
    Sets.mutable.with("a", "b");
MutableSet<String> synchronizedMutableSet =
    Sets.mutable.with("a", "b").asSynchronized();
MutableSet<String> unmodifiableMutableSet =
    Sets.mutable.with("a", "b").asUnmodifiable();

ImmutableSet<String> immutableSet =
    Sets.immutable.with("a", "b");
ImmutableSet<String> immutableSet2 =
    Sets.mutable.with("a", "b").toImmutable();

CharSet charSet =
    CharSets.mutable.with('a', 'b');
CharSet synchronizedCharSet =
    CharSets.mutable.with('a', 'b').asSynchronized();
CharSet unmodifiableCharSet =
    CharSets.mutable.with('a', 'b').asUnmodifiable();
MutableCharSet mutableCharSet =
    CharSets.mutable.with('a', 'b');
ImmutableCharSet immutableCharSet =
    CharSets.immutable.with('a', 'b');
ImmutableCharSet immutableCharSet2 =
    CharSets.mutable.with('a', 'b').toImmutable();

Eclipse Collections совместима с Java 5 - 8.

Примечание: я являюсь коммиттером для Eclipse Collections.

4 голосов
/ 09 августа 2017

(некрасиво) Инициализация двойной скобки без побочных эффектов:

Set<String> a = new HashSet<>(new HashSet<String>() {{
    add("1");
    add("2");
}})

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

final Set<String> a = Collections.unmodifiableSet(new HashSet<String>(){{
    add("1");
    add("2");
}})
4 голосов
/ 11 января 2010

Немного запутанный, но работает с Java 5:

Set<String> h = new HashSet<String>(Arrays.asList(new String[] {  
    "a", "b"
}))

Используйте вспомогательный метод, чтобы сделать его читаемым:

Set<String> h = asSet ("a", "b");

public Set<String> asSet(String... values) {
    return new HashSet<String>(java.util.Arrays.asList(values));
}
3 голосов
/ 08 декабря 2017

Используя Java 8 , мы можем создать HashSet как:

Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new));

И если нам нужен немодифицируемый набор, мы можем создать служебный метод как:

public static <T, A extends Set<T>> Collector<T, A, Set<T>> toImmutableSet(Supplier<A> supplier) {
        return Collector.of(
                supplier,
                Set::add, (left, right) -> {
                    left.addAll(right);
                    return left;
                }, Collections::unmodifiableSet);
    }

Этот метод можно использовать как:

 Stream.of("A", "B", "C", "D").collect(toImmutableSet(HashSet::new));
3 голосов
/ 11 ноября 2015

Просто небольшая заметка, независимо от того, с каким из подходов, упомянутых здесь, вы в конечном итоге остановитесь, если это значение по умолчанию, которое обычно остается неизменным (как значение по умолчанию в создаваемой вами библиотеке), это хорошая идея для следуйте этой схеме:

// Initialize default values with the method you prefer, even in a static block
// It's a good idea to make sure these defaults aren't modifiable
private final static Set<String> DEFAULT_VALUES = Collections.unmodifiableSet(...);
private Set<String> values = DEFAULT_VALUES;

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

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

2 голосов
/ 27 сентября 2017

С выпуском и фабричных методов удобства это возможно более чистым способом:

Set set = Set.of("a", "b", "c");
1 голос
/ 17 мая 2017

Может использовать статический блок для инициализации:

private static Set<Integer> codes1=
        new HashSet<Integer>(Arrays.asList(1, 2, 3, 4));

private static Set<Integer> codes2 =
        new HashSet<Integer>(Arrays.asList(5, 6, 7, 8));

private static Set<Integer> h = new HashSet<Integer>();

static{
    h.add(codes1);
    h.add(codes2);
}
...