如何通过构造来初始化HashSet值?

发布于 2024-08-17 09:50:28 字数 180 浏览 4 评论 0原文

我需要创建一个带有初始值的Set

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

有没有办法用一行代码来做到这一点?例如,它对于最终静态字段很有用。

I need to create a Set with initial values.

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

Is there a way to do this in one line of code? For instance, it's useful for a final static field.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(25

盛夏已如深秋| 2024-08-24 09:50:28

我使用的速记不是很省时,但适合单行:

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

同样,这不是很省时,因为您正在构造一个数组,转换为一个列表并使用该列表来创建一个集合。

当初始化静态最终集时,我通常这样写:

public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));

稍微不那么难看,并且效率对于静态初始化来说并不重要。

There is a shorthand that I use that is not very time efficient, but fits on a single line:

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

Again, this is not time efficient since you are constructing an array, converting to a list and using that list to create a set.

When initializing static final sets I usually write it like this:

public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));

Slightly less ugly and efficiency does not matter for the static initialization.

隔岸观火 2024-08-24 09:50:28

集合文字原定在 Java 7 中使用,但没有实现。所以还没有什么自动的。

您可以使用 guava 的 Sets

Sets.newHashSet("a", "b", "c")

或者您可以使用以下语法,这将创建一个匿名类,但它很hacky:

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

Collection literals were scheduled for Java 7, but didn't make it in. So nothing automatic yet.

You can use guava's Sets:

Sets.newHashSet("a", "b", "c")

Or you can use the following syntax, which will create an anonymous class, but it's hacky:

Set<String> h = new HashSet<String>() {{
    add("a");
    add("b");
}};
胡渣熟男 2024-08-24 09:50:28

如果您正在寻找初始化集合的最紧凑的方法,那么 Java9 中就是:

Set<String> strSet = Set.of("Apple", "Ball", "Cat", "Dog");

===================== 详细答案如下==========================

使用 Java 10(不可修改集)

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toUnmodifiableSet());

这里收集器实际上会返回 Java 9 中引入的不可修改集,从语句set ->源代码中的 (Set)Set.of(set.toArray())

需要注意的一点是方法Collections.unmodifyingSet() 返回指定集的不可修改视图(根据文档)。 不可修改的视图集合是不可修改的集合,也是支持集合的视图。请注意,对支持集合的更改可能仍然是可能的,并且如果发生,它们可以通过不可修改的视图可见。但是方法 Collectors .toUnmodifyingSet() 返回 Java 10 中的真正不可变集。


使用 Java 9(不可修改的集)

以下是初始化集的最紧凑方式:

Set<String> strSet6 = Set.of("Apple", "Ball", "Cat", "Dog");

我们有 12 个重载版本便利工厂方法:

静态;设置of()

静态;设置of(E e1)

静态;设置of(E e1, E e2)

// ....等等

静态;设置of(E... 元素)

那么一个自然的问题是为什么当我们有 var-args 时我们需要重载版本?答案是:每个 var-arg 方法都会在内部创建一个数组,并且具有重载版本可以避免不必要的对象创建,并且还可以节省我们的垃圾收集开销。


使用 Java 8(可修改集)

使用 Stream。

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toCollection(HashSet::new));

// stream from an array (String[] stringArray)
Set<String> strSet2 = Arrays.stream(stringArray)
         .collect(Collectors.toCollection(HashSet::new));

// stream from a list (List<String> stringList)
Set<String> strSet3 = stringList.stream()
         .collect(Collectors.toCollection(HashSet::new));

使用 Java 8(不可修改集)

使用 Collections.unmodifyingSet()

我们可以使用 Collections.unmodifyingSet() as:

Set<String> strSet4 = Collections.unmodifiableSet(strSet1);

但是看起来有点尴尬,我们可以像这样编写自己的收集器:

class ImmutableCollector {
    public static <T> Collector<T, Set<T>, Set<T>> toImmutableSet() {
        return Collector.of(HashSet::new, Set::add, (l, r) -> {
            l.addAll(r);
            return l;
        }, Collections::unmodifiablSet);
    }
}

然后将其用作:

Set<String> strSet4 = Stream.of("A", "B", "C", "D")
             .collect(ImmutableCollector.toImmutableSet());

使用 Collectors.collectingAndThen()

另一种方法是使用方法 Collectors.collectingAndThen() 让我们执行额外的整理转换:

import static java.util.stream.Collectors.*;
Set<String> strSet5 = Stream.of("A", "B", "C", "D").collect(collectingAndThen(
   toCollection(HashSet::new),Collections::unmodifiableSet));

如果我们只关心 Set 那么我们也可以使用 Collectors.toSet() 代替 Collectors.toCollection(HashSet::new)

另请检查 Java 8 的答案。

If you are looking for the most compact way of initializing a set then that was in Java9:

Set<String> strSet = Set.of("Apple", "Ball", "Cat", "Dog");

===================== Detailed answer below ==========================

Using Java 10 (Unmodifiable Sets)

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toUnmodifiableSet());

Here the collector would actually return the unmodifiable set introduced in Java 9 as evident from the statement set -> (Set<T>)Set.of(set.toArray()) in the source code.

One point to note is that the method Collections.unmodifiableSet() returns an unmodifiable view of the specified set (as per documentation). An unmodifiable view collection is a collection that is unmodifiable and is also a view onto a backing collection. Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view. But the method Collectors.toUnmodifiableSet() returns truly immutable set in Java 10.


Using Java 9 (Unmodifiable Sets)

The following is the most compact way of initializing a set:

Set<String> strSet6 = Set.of("Apple", "Ball", "Cat", "Dog");

We have 12 overloaded versions of this convenience factory method:

static <E> Set<E> of()

static <E> Set<E> of(E e1)

static <E> Set<E> of(E e1, E e2)

// ....and so on

static <E> Set<E> of(E... elems)

Then a natural question is why we need overloaded versions when we have var-args? The answer is: every var-arg method creates an array internally and having the overloaded versions would avoid unnecessary creation of object and will also save us from the garbage collection overhead.


Using Java 8 (Modifiable Sets)

Using Stream in Java 8.

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toCollection(HashSet::new));

// stream from an array (String[] stringArray)
Set<String> strSet2 = Arrays.stream(stringArray)
         .collect(Collectors.toCollection(HashSet::new));

// stream from a list (List<String> stringList)
Set<String> strSet3 = stringList.stream()
         .collect(Collectors.toCollection(HashSet::new));

Using Java 8 (Unmodifiable Sets)

Using Collections.unmodifiableSet()

We can use Collections.unmodifiableSet() as:

Set<String> strSet4 = Collections.unmodifiableSet(strSet1);

But it looks slightly awkward and we can write our own collector like this:

class ImmutableCollector {
    public static <T> Collector<T, Set<T>, Set<T>> toImmutableSet() {
        return Collector.of(HashSet::new, Set::add, (l, r) -> {
            l.addAll(r);
            return l;
        }, Collections::unmodifiablSet);
    }
}

And then use it as:

Set<String> strSet4 = Stream.of("A", "B", "C", "D")
             .collect(ImmutableCollector.toImmutableSet());

Using Collectors.collectingAndThen()

Another approach is to use the method Collectors.collectingAndThen() which lets us perform additional finishing transformations:

import static java.util.stream.Collectors.*;
Set<String> strSet5 = Stream.of("A", "B", "C", "D").collect(collectingAndThen(
   toCollection(HashSet::new),Collections::unmodifiableSet));

If we only care about Set then we can also use Collectors.toSet() in place of Collectors.toCollection(HashSet::new).

Also check this answer for Java 8.

氛圍 2024-08-24 09:50:28

在 Java 8 中,我会使用:

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

这为您提供了一个用“a”和“b”预先初始化的可变 Set。请注意,虽然在 JDK 8 中,这确实返回一个 HashSet,但规范并不保证它,并且将来可能会发生变化。如果您特别想要一个 HashSet,请执行以下操作:

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

In Java 8 I would use:

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

This gives you a mutable Set pre-initialized with "a" and "b". Note that while in JDK 8 this does return a HashSet, the specification doesn't guarantee it, and this might change in the future. If you specifically want a HashSet, do this instead:

Set<String> set = Stream.of("a", "b")
                        .collect(Collectors.toCollection(HashSet::new));
爱的故事 2024-08-24 09:50:28

有几种方法:

双括号初始化

这是一种创建匿名内部类的技术,该内部类具有实例初始值设定项,在创建实例时将 String 添加到自身:

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

请记住,这实际上会创建 < 的新子类code>HashSet 每次使用时,即使不必显式编写新的子类。

实用方法

编写返回 Set 编写起来并不难:

public static Set<String> newHashSet(String... strings) {
    HashSet<String> set = new HashSet<String>();

    for (String s : strings) {
        set.add(s);
    }
    return set;
}

上面的代码只允许使用 String,但是允许使用任何使用泛型的类型应该不会太困难。

使用库

许多库都有一个方便的方法来初始化集合对象。

例如,Google 收藏集有一个 Sets.newHashSet(T...) 方法将使用特定类型的元素填充HashSet

There are a few ways:

Double brace initialization

This is a technique which creates an anonymous inner class which has an instance initializer which adds Strings to itself when an instance is created:

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

Keep in mind that this will actually create an new subclass of HashSet each time it is used, even though one does not have to explicitly write a new subclass.

A utility method

Writing a method that returns a Set which is initialized with the desired elements isn't too hard to write:

public static Set<String> newHashSet(String... strings) {
    HashSet<String> set = new HashSet<String>();

    for (String s : strings) {
        set.add(s);
    }
    return set;
}

The above code only allows for a use of a String, but it shouldn't be too difficult to allow the use of any type using generics.

Use a library

Many libraries have a convenience method to initialize collections objects.

For example, Google Collections has a Sets.newHashSet(T...) method which will populate a HashSet with elements of a specific type.

山色无中 2024-08-24 09:50:28

最方便的方法之一是使用通用 Collections.addAll() 方法,它接受一个集合和可变参数:

Set<String> h = new HashSet<String>();
Collections.addAll(h, "a", "b");

One of the most convenient ways is usage of generic Collections.addAll() method, which takes a collection and varargs:

Set<String> h = new HashSet<String>();
Collections.addAll(h, "a", "b");
萌无敌 2024-08-24 09:50:28

如果您只有一个值并且想要获得一个不可变集,这就足够了:

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

If you have only one value and want to get an immutable set this would be enough:

Set<String> immutableSet = Collections.singleton("a");
掌心的温暖 2024-08-24 09:50:28

使用 Java 9,您可以执行以下操作:

Set.of("a", "b");

您将获得一个包含元素的不可变 Set。详细信息请参见Oracle接口Set的文档

With Java 9 you can do the following:

Set.of("a", "b");

and you'll get an immutable Set containing the elements. For details see the Oracle documentation of interface Set.

清秋悲枫 2024-08-24 09:50:28

您可以在 Java 6 中做到这一点:

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

但是为什么呢?我认为它比显式添加元素更具可读性。

You can do it in Java 6:

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

But why? I don't find it to be more readable than explicitly adding elements.

野生奥特曼 2024-08-24 09:50:28

我觉得最具可读性的是简单地使用 google Guava

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

它是可变的。

I feel the most readable is to simply use google Guava:

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

It's mutable.

烟若柳尘 2024-08-24 09:50:28

如果 Set 包含的类型是枚举,则有 java 内置的工厂方法(自 1.5 起):

Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... );

If the contained type of the Set is an enumeration then there is java built factory method (since 1.5):

Set<MY_ENUM> MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... );
爱殇璃 2024-08-24 09:50:28

coobird 的答案用于创建新实用程序函数的概括>哈希集

public static <T> Set<T> newHashSet(T... objs) {
    Set<T> set = new HashSet<T>();
    for (T o : objs) {
        set.add(o);
    }
    return set;
}

A generalization of coobird's answer's utility function for creating new HashSets:

public static <T> Set<T> newHashSet(T... objs) {
    Set<T> set = new HashSet<T>();
    for (T o : objs) {
        set.add(o);
    }
    return set;
}
巷雨优美回忆 2024-08-24 09:50:28
import com.google.common.collect.Sets;
Sets.newHashSet("a", "b");

或者

import com.google.common.collect.ImmutableSet;
ImmutableSet.of("a", "b");
import com.google.common.collect.Sets;
Sets.newHashSet("a", "b");

or

import com.google.common.collect.ImmutableSet;
ImmutableSet.of("a", "b");
嘴硬脾气大 2024-08-24 09:50:28

使用 Eclipse Collections 有几种不同的方法来初始化包含以下内容的 Set一条语句中的字符“a”和“b”。 Eclipse Collections 具有对象和基本类型的容器,因此我说明了如何使用 SetCharSet 除了可变、不可变、同步和不可修改版本之外两者都有。

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 的提交者。

With Eclipse Collections there are a few different ways to initialize a Set containing the characters 'a' and 'b' in one statement. Eclipse Collections has containers for both object and primitive types, so I illustrated how you could use a Set<String> or CharSet in addition to mutable, immutable, synchronized and unmodifiable versions of both.

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();

Note: I am a committer for Eclipse Collections.

挽清梦 2024-08-24 09:50:28

随着 便利工厂方法这是可能的以更干净的方式:

Set set = Set.of("a", "b", "c");

With the release of and the convenience factory methods this is possible in a cleaner way:

Set set = Set.of("a", "b", "c");
决绝 2024-08-24 09:50:28

只是一个小注意事项,无论您最终采用哪种这里提到的好方法,如果这是通常未经修改的默认设置(例如您正在创建的库中的默认设置),那么遵循此模式是一个好主意:

// 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;

好处取决于您为该类创建的实例数量以及默认值更改的可能性。

如果您决定遵循此模式,那么您还可以选择最具可读性的集初始化方法。由于不同方法之间效率的微小差异可能并不重要,因为您只需初始化该集合一次。

Just a small note, regardless of which of the fine approaches mentioned here you end up with, if this is a default that usually goes unmodified (like a default setting in a library you are creating), it is a good idea to follow this pattern:

// 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;

The benefit depends on the number of instances you create of that class and how likely it's that defaults will be changed.

If you decide to follow this pattern, then you also get to pick the method of set initialization that's most readable. As the micro differences in efficiency between the different methods will probably not matter much as you will be initializing the set only once.

对岸观火 2024-08-24 09:50:28

(丑陋的)双括号初始化没有副作用:

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");
}})

(ugly) Double Brace Initialization without side effects:

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

But in some cases, if we mentioned that is a good smell to make final collections unmutable, it could be really useful:

final Set<String> a = Collections.unmodifiableSet(new HashSet<String>(){{
    add("1");
    add("2");
}})
清晰传感 2024-08-24 09:50:28

有点复杂,但从 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));
}

A bit convoluted but works from Java 5:

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

Use a helper method to make it readable:

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

public Set<String> asSet(String... values) {
    return new HashSet<String>(java.util.Arrays.asList(values));
}
海夕 2024-08-24 09:50:28

使用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));

Using Java 8 we can create HashSet as:

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

And if we want unmodifiable set we can create a utility method as :

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);
    }

This method can be used as :

 Stream.of("A", "B", "C", "D").collect(toImmutableSet(HashSet::new));
蓝眼泪 2024-08-24 09:50:28

可以使用静态块进行初始化:

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);
}

Can use static block for initialization:

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);
}
暮年 2024-08-24 09:50:28

这是一个优雅的解决方案:

public static final <T> Set<T> makeSet(@SuppressWarnings("unchecked") T... o) {
        return new HashSet<T>() {
            private static final long serialVersionUID = -3634958843858172518L;
            {
                for (T x : o)
                   add(x);
            }
        };
}

This is an elegant solution:

public static final <T> Set<T> makeSet(@SuppressWarnings("unchecked") T... o) {
        return new HashSet<T>() {
            private static final long serialVersionUID = -3634958843858172518L;
            {
                for (T x : o)
                   add(x);
            }
        };
}
温柔一刀 2024-08-24 09:50:28

建造者模式可能在这里有用。今天我遇到了同样的问题。我需要 Set 变异操作来返回 Set 对象的引用,这样我就可以将它传递给超类构造函数,以便它们也可以通过依次从子类的 Set 构造一个新的 StringSetBuilder 来继续添加到同一个集合中刚刚建成。我编写的构建器类如下所示(在我的例子中,它是外部类的静态内部类,但它也可以是它自己的独立类):

public interface Builder<T> {
    T build();
}

static class StringSetBuilder implements Builder<Set<String>> {
    private final Set<String> set = new HashSet<>();

    StringSetBuilder add(String pStr) {
        set.add(pStr);
        return this;
    }

    StringSetBuilder addAll(Set<String> pSet) {
        set.addAll(pSet);
        return this;
    }

    @Override
    public Set<String> build() {
        return set;
    }
}

注意 addAll()add() 方法,它们是返回 Set.add()Set.addAll() 对应项的 Set。最后请注意 build() 方法,该方法返回对构建器封装的 Set 的引用。下面说明了如何使用此集合构建器:

class SomeChildClass extends ParentClass {
    public SomeChildClass(String pStr) {
        super(new StringSetBuilder().add(pStr).build());
    }
}

class ParentClass {
    public ParentClass(Set<String> pSet) {
        super(new StringSetBuilder().addAll(pSet).add("my own str").build());
    }
}

The Builder pattern might be of use here. Today I had the same issue. where I needed Set mutating operations to return me a reference of the Set object, so I can pass it to super class constructor so that they too can continue adding to same set by in turn constructing a new StringSetBuilder off of the Set that the child class just built. The builder class I wrote looks like this (in my case it's a static inner class of an outer class, but it can be its own independent class as well):

public interface Builder<T> {
    T build();
}

static class StringSetBuilder implements Builder<Set<String>> {
    private final Set<String> set = new HashSet<>();

    StringSetBuilder add(String pStr) {
        set.add(pStr);
        return this;
    }

    StringSetBuilder addAll(Set<String> pSet) {
        set.addAll(pSet);
        return this;
    }

    @Override
    public Set<String> build() {
        return set;
    }
}

Notice the addAll() and add() methods, which are Set returning counterparts of Set.add() and Set.addAll(). Finally notice the build() method, which returns a reference to the Set that the builder encapsulates. Below illustrates then how to use this Set builder:

class SomeChildClass extends ParentClass {
    public SomeChildClass(String pStr) {
        super(new StringSetBuilder().add(pStr).build());
    }
}

class ParentClass {
    public ParentClass(Set<String> pSet) {
        super(new StringSetBuilder().addAll(pSet).add("my own str").build());
    }
}
想念有你 2024-08-24 09:50:28

Michael Berdyshev 的答案与泛型相结合,并使用带有initialCapacity的构造函数,与 Arrays.asList 变体进行比较:

  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Set;

  @SafeVarargs
  public static <T> Set<T> buildSetModif(final T... values) {
    final Set<T> modifiableSet = new HashSet<T>(values.length);
    Collections.addAll(modifiableSet, values);
    return modifiableSet;
  }

  @SafeVarargs
  public static <T> Set<T> buildSetModifTypeSafe(final T... values) {
    return new HashSet<T>(Arrays.asList(values));
  }

  @SafeVarargs
  public static <T> Set<T> buildeSetUnmodif(final T... values) {
    return Collections.unmodifiableSet(buildSetModifTypeSafe(values));
    // Or use Set.of("a", "b", "c") if you use Java 9
  }
  • 如果您为 init 传递一些值,对于任何大的值,这很好
    使用其他方法
  • 如果您不小心将类型与 buildSetModif 混合使用,则生成的 T 将
    是<代码>? extends Object,这可能不是您想要的,使用 buildSetModifTypeSafe 变体不会发生这种情况,这意味着 buildSetModifTypeSafe(1, 2, "a");不会编译

Combining answer by Michael Berdyshev with Generics and using constructor with initialCapacity, comparing with Arrays.asList variant:

  import java.util.Collections;
  import java.util.HashSet;
  import java.util.Set;

  @SafeVarargs
  public static <T> Set<T> buildSetModif(final T... values) {
    final Set<T> modifiableSet = new HashSet<T>(values.length);
    Collections.addAll(modifiableSet, values);
    return modifiableSet;
  }

  @SafeVarargs
  public static <T> Set<T> buildSetModifTypeSafe(final T... values) {
    return new HashSet<T>(Arrays.asList(values));
  }

  @SafeVarargs
  public static <T> Set<T> buildeSetUnmodif(final T... values) {
    return Collections.unmodifiableSet(buildSetModifTypeSafe(values));
    // Or use Set.of("a", "b", "c") if you use Java 9
  }
  • This is good if you pass a few values for init, for anything large
    use other methods
  • If you accidentally mix types with buildSetModif the resulting T will
    be ? extends Object, which is probably not what you want, this cannot happen with the buildSetModifTypeSafe variant, meaning that buildSetModifTypeSafe(1, 2, "a"); will not compile
傲世九天 2024-08-24 09:50:28

您还可以使用 vavr

import io.vavr.collection.HashSet;

HashSet.of("a", "b").toJavaSet();

You can also use vavr:

import io.vavr.collection.HashSet;

HashSet.of("a", "b").toJavaSet();
鹿港小镇 2024-08-24 09:50:28

为了填充增量整数值或简单地用值 x 初始化长度为 n 的集合,我们可以这样做:

(Java 8)

int n = 10; // length of 10

填充从 0 到 9 的所有值(n-1,增量 10 个值):

IntStream.range(0, n).forEach(h::add);

或者,填充所有值常量值:

IntStream.range(0, n).forEach(()->h.add(12345));

或者也使用 Stream,填充现有列表:

myList.forEach(h::add); // assuming type of myList is List<Integer>

最后,将其与匿名构造函数结合使用,例如其中之一

HashSet<Integer> h = new HashSet(){{IntStream.range(0, n).forEach(h::add);}}; // incremental
HashSet<Integer> h = new HashSet(){{IntStream.range(0, n).forEach(()->h.add(12345));}}; // constant
HashSet<Integer> h = new HashSet(){{myList.forEach(h::add);}}; // List

此代码基本上缩短了经典的 for 循环,因此效率不高,但适合一行

For filling with incremental integer values or simply initialize the set of length n with value x we can do:

(Java 8)

int n = 10; // length of 10

to fill all the value from 0 to 9 (n-1, 10 values incrementally):

IntStream.range(0, n).forEach(h::add);

or, to fill all with a constant value:

IntStream.range(0, n).forEach(()->h.add(12345));

or also using Stream, to fill with an existing list:

myList.forEach(h::add); // assuming type of myList is List<Integer>

Finally, combine this with anonymous constructor, e.g. one of these

HashSet<Integer> h = new HashSet(){{IntStream.range(0, n).forEach(h::add);}}; // incremental
HashSet<Integer> h = new HashSet(){{IntStream.range(0, n).forEach(()->h.add(12345));}}; // constant
HashSet<Integer> h = new HashSet(){{myList.forEach(h::add);}}; // List

This code basically shorten the classic for-loop, so not so efficient but fits in one line

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文