Immutable Set in Java – Java中的不可变集

最后修改: 2019年 1月 4日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this tutorial, we’re going to have a look at different ways of constructing an immutable set in Java.

在本教程中,我们将看看在Java中构建不可变集合的不同方法。

But first, let’s understand the immutable set and see why we need it.

但首先,让我们了解一下不可变集,看看我们为什么需要它。

2. What Is an Immutable Set?

2.什么是不可改变的集合?

In general, an immutable object will not change its internal state once we create it. This makes it thread-safe by default. The same logic applies to immutable sets.

一般来说,一旦我们创建了一个不可变对象,就不会改变其内部状态。这使得它默认为线程安全的。同样的逻辑也适用于不可变的集合。

Let’s suppose we have a HashSet instance with some values. Making it immutable will create a “read-only” version of our set. Thus, any attempt to modify its state will throw UnsupportedOperationException.

假设我们有一个带有一些值的HashSet实例。让它成为不可变的,将为我们的集合创建一个 “只读 “的版本。因此,任何修改其状态的尝试都会抛出不支持操作的异常

So, why do we need it?

那么,我们为什么需要它呢?

Certainly, the most common use case of an immutable set is a multi-threaded environment. So, we can share immutable data across the threads without worrying about the synchronization.

当然,不可变集最常见的使用情况是多线程环境。因此,我们可以在各线程之间共享不可变的数据,而不必担心同步问题。

Meanwhile, there’s an important point to keep in mind: immutability pertains only to the set and not to its elements. Furthermore, we can modify the instance references of the set elements without a problem.

同时,有一个重要的问题要记住。immutability只涉及到集合,而不是其元素。此外,我们可以毫无问题地修改集合元素的实例引用。

3. Create Immutable Sets in Core Java

3.在Core Java中创建不可变的集合

With just the core Java classes at our disposal, we can use the Collections.unmodifiableSet() method to wrap the original Set.

只需掌握核心的Java类,我们就可以使用Collections.unmodifiableSet()方法来包装原来的Set

First, let’s create a simple HashSet instance and initialize it with String values:

首先,让我们创建一个简单的HashSet实例,并用String值将其初始化。

Set<String> set = new HashSet<>();
set.add("Canada");
set.add("USA");

Next, let’s wrap it up with Collections.unmodifiableSet():

接下来,让我们用Collections.unmodifiableSet()把它包起来:

Set<String> unmodifiableSet = Collections.unmodifiableSet(set);

Finally, to make sure our unmodifiableSet instance is immutable, let’s create a simple test case:

最后,为了确保我们的unmodifiableSet实例是不可更改的,让我们创建一个简单的测试案例。

@Test(expected = UnsupportedOperationException.class)
public void testUnmodifiableSet() {
    // create and initialize the set instance

    Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
    unmodifiableSet.add("Costa Rica");
}

As we expect, the test will run successfully. Furthermore, the add() operation is prohibited on the unmodifiableSet instance and will throw UnsupportedOperationException.

正如我们所期望的,测试将成功运行。此外,add()操作在unmodifiableSet实例上是被禁止的,将抛出UnsupportedOperationException

Now, let’s change the initial set instance by adding the same value to it:

现在,让我们改变初始的set实例,给它添加同样的值。

set.add("Costa Rica");

This way, we indirectly modify the unmodifiable set. So, when we print the unmodifiableSet instance:

这样一来,我们就间接地修改了不可修改的集合。所以,当我们打印unmodifiableSet实例时。

[Canada, USA, Costa Rica]

As we can see, the “Costa Rica” item is also present in unmodifiableSet.

我们可以看到,“哥斯达黎加”项也存在于不可修改集中。

4. Create Immutable Sets in Java 9

4.在Java 9中创建不可变的集合

Since Java 9, the Set.of(elements) static factory method is available for creating immutable sets:

从Java 9开始,Set.of(elements)静态工厂方法可用于创建不可变的集合。

Set<String> immutable = Set.of("Canada", "USA");

5. Create Immutable Sets in Guava

5.在Guava中创建不可变的集合

Another way that we can construct an immutable set is by using Guava’s ImmutableSet class. It copies the existing data into a new immutable instance. As a result, the data inside ImmutableSet won’t change when we alter the original Set.

我们可以通过使用Guava的ImmutableSet类来构建一个不可变的集合的另一种方式。它将现有的数据复制到一个新的不可变的实例中。因此,当我们改变原始的Set时,ImmutableSet中的数据将不会改变。

Like the core Java implementation, any attempt to modify the created immutable instance will throw UnsupportedOperationException.

与核心Java实现一样,任何试图修改已创建的不可变实例的行为都会抛出不支持的操作异常

Now, let’s explore different ways of creating immutable instances.

现在,让我们探讨一下创建不可变实例的不同方法。

5.1. Using ImmutableSet.copyOf()

5.1.使用ImmutableSet.copyOf()

Simply put, the ImmutableSet.copyOf() method returns a copy of all the elements in the set:

简单地说,ImmutableSet.copyOf()方法返回集合中所有元素的一个副本。

Set<String> immutable = ImmutableSet.copyOf(set);

So, after changing the initial set, the immutable instance will stay the same:

因此,在改变初始集合后,不可变的实例将保持不变。

[Canada, USA]

5.2. Using ImmutableSet.of()

5.2.使用ImmutableSet.of()

Similarly, with the ImmutableSet.of() method we can instantly create an immutable set with the given values:

同样地,通过ImmutableSet.of()方法,我们可以立即用给定的值创建一个不可变的集合。

Set<String> immutable = ImmutableSet.of("Canada", "USA");

When we don’t specify any elements, the ImmutableSet.of() will return an empty immutable set.

当我们没有指定任何元素时,ImmutableSet.of()将返回一个空的不可变集合。

This can be compared to Java 9’s Set.of().

这可以与Java 9的Set.of().相比。

6. Conclusion

6.结论

In this quick article, we discussed immutable Sets in the Java language. Moreover, we showed how to create immutable Sets using the Collections API from core Java, Java 9 and the Guava library.

在这篇快速文章中,我们讨论了Java语言中不可变的Sets此外,我们展示了如何使用核心Java、Java 9和Guava库中的集合API创建不可变的Sets

Finally, as usual, the complete code for this article is available over on GitHub.

最后,像往常一样,本文的完整代码可以在GitHub上找到