Java不可变集的示例

时间:2020-01-09 10:35:03  来源:igfitidea点击:

在Java 9中,添加了新的静态工厂方法以在Java中创建不可变的Set。在本文中,我们将看到一个使用工厂方法创建不可变集合的示例,以及如何使其比以前使用Collections.unmodifiableSet()的选项更方便。

我们不能从不可变集合中删除或者添加元素。在Set上调用任何mutator方法将始终导致抛出UnsupportedOperationException。

在Java 9之前创建不可变或者不可修改的集合

在Java 9之前,Collections.unmodifiableSet()方法用于创建不可变集。使用此方法要注意的一件事是仍可以修改原始集。

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

public class ImmutSet {
  public static void main(String[] args) {
    Set<String> numSet = new HashSet<>();
    numSet.add("1");
    numSet.add("2");
    numSet.add("3");
    numSet.add("4");
    Set<String> iSet = Collections.unmodifiableSet(numSet);
    numSet.add("5");
    System.out.println("Numbers- " + numSet);
    // Throws Exception as this set is an unmodifiable view
    iSet.add("6");
  }
}

输出:

Numbers- [1, 2, 3, 4, 5]

Exception in thread "main" 
java.lang.UnsupportedOperationException
	at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1058)
	at com.theitroad.proj.Programs.ImmutSet.main(ImmutSet.java:19)

如我们所见,原始集合(numSet)仍可以修改。如下所述,可以用较少冗长的方式完成相同的操作

public class ImmutSet {
  public static void main(String[] args) {
    Set<String> numSet = new HashSet<>(Arrays.asList("1", "2", "3", "4"));
    numSet = Collections.unmodifiableSet(numSet);
  }
}

向前创建不可变集Java 9

从Java 9开始,有两种方便的静态工厂方法可用于创建不可变的Set。

  • Set.of()(在Java 9中添加)
  • Set.copyOf()(在Java 10中添加)

这些方法创建的Set实例具有以下特征:

  • 它们是不可修改的。元素无法添加或者删除。调用Set上的任何mutator方法将始终引发UnsupportedOperationException。但是,如果所包含的元素本身是可变的,则可能导致Set的行为不一致或者它的内容似乎发生变化。
  • 这些方法不允许使用null元素。尝试使用null元素创建它们会导致NullPointerException。
  • 如果所有元素都是可序列化的,则它们是可序列化的。
  • 他们在创建时拒绝重复的元素。传递给静态工厂方法的重复元素将导致IllegalArgumentException。
  • set元素的迭代顺序未指定,可能会发生变化。

Set.of()方法示例

Set.of方法具有许多重载形式,使我们可以选择创建0到10个元素的set。

of()返回一个包含零元素的不可修改的集合。
of(E e1)返回包含一个元素的不可修改的集合。
of(E e1,E e2)返回包含两个元素的不可修改的集合。
..
..
of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8,E e9)返回包含9个元素的不可修改集合。
of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8,E e9,E e10)返回包含十个元素的不可修改的集合。

还有一个可变参数形式

of(E…elements)返回一个不可修改的集合,其中包含任意数量的元素。

import java.util.Set;

public class ImmutSet {
  public static void main(String[] args) {
    Set<String> numSet = Set.of("1", "2", "3", "4");
    System.out.println("numSet- " + numSet);
    //Throws exception as the Set is immutable
    numSet.add("5");
  }
}

输出:

numSet- [3, 4, 1, 2]
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:72)
	at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:76)
	at com.theitroad.proj.Programs.ImmutSet.main(ImmutSet.java:10)

Set.copyOf()方法示例

如果要从任何给定的集合创建不可变集合,则可以使用此方法。给定的Collection不能为null,并且不得包含任何null元素。如果给定的Collection随后被修改,则返回的Set将不会反映这种修改。

public class ImmutSet {
  public static void main(String[] args) {
    Set<String> numSet = new HashSet<>();
    numSet.add("1");
    numSet.add("2");
    numSet.add("3");
    numSet.add("4");
    System.out.println("numSet- " + numSet);
    Set<String> iSet = Set.copyOf(numSet);
    System.out.println("Immutable Set- " + iSet);

    numSet.add("5");
    System.out.println("numSet after modification- " + numSet);
    System.out.println("Immutable Set- " + iSet);
  }
}

输出:

numSet- [1, 2, 3, 4]
Immutable Set- [1, 2, 3, 4]
numSet after modification- [1, 2, 3, 4, 5]
Immutable Set- [1, 2, 3, 4]

如我们所见,修改用于创建不可变集合的集合时,更改不会反映到集合中。