Java 9:什么是集合工厂方法?

时间:2017-04-21 04:13:00

标签: java collections factory literals java-9

Java 9的到来为Java的Collections API带来了许多新功能,其中一个是集合工厂方法。

它们是什么以及如何正确实施?

1 个答案:

答案 0 :(得分:9)

注1:为了防止使用raw-types,我选择使用E为我在下面提到的每个类提供泛型类型,表示{的一个元素{1}}。

注2:这个答案可能会有所变化;如果发生拼写错误,请编辑此帖子。

什么是集合工厂方法?

Java中的集合工厂方法是一种静态方法,它提供了一种初始化不可变 Collection<E>的简单方法。

不可变,在初始化Collection<E>后,Collection<E>内无法添加,删除或修改任何元素。

使用Java 9,为以下接口提供了集合工厂方法:List<E>Set<E>Map<K, V>

他们有什么改进?

直到Java 9,没有简单的通用方法来初始化具有初始元素/键值条目的Collection<E>。以前,开发人员需要按如下方式初始化它们(假设通用类型EKV已替换为Integer):

  • List<Integer>
    • 以下方法最简单的方法是使用初始元素初始化List<Integer>,但结果只是List<Integer>的视图;我们无法添加或删除此List<Integer>,但我们仍然可以使用List#set修改现有元素。
      • List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    • 如果我们希望我们的List<Integer>完全可变,那么我们必须将它传递给ArrayList<Integer>的构造函数,例如:
      • List<Integer> mutableList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
  • Set<Integer>
    • Set<Integer>需要使用初始元素进行初始化的代码多于List<Integer>(使用初始元素初始化List<Integer>需要Set<Integer>),可以在下面看到。
      • Set<Integer> mutableSet = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
  • Map<Integer, Integer>
    • 使用初始键值条目初始化时,Map<Integer, Integer>可能是最复杂的;但是,有多种方法可以解决这个问题。
      • 一种方法是先初始化一个空Map<Integer, Integer>,然后只需调用Map#put即可添加键值条目。
      • 另一种方法是使用带有两个花括号的匿名类,这仍然需要调用Map#put

我为什么要使用它们?

我认为集合工厂方法为开发人员提供了一种初始化List<E>Set<E>Map<K, V>的简明方法,其中包含初始元素/键值条目,可以看到通过以下示例。

使用的正确语法是什么?

为简单起见,这些示例将使用E替换通用类型KVInteger

  • List<Integer>
    • List<Integer> list = List.of();
      • 初始化一个空的,不可变的List<Integer>
    • List<Integer> list = List.of(1);
      • 使用一个元素初始化不可变List<Integer>
    • List<Integer> list = List.of(1, 2);
      • 使用两个元素初始化不可变List<Integer>
    • List<Integer> list = List.of(1, 2, 3, 4, 5, ...);
      • 使用可变数量的元素初始化不可变List<Integer>
  • Set<Integer>
    • Set<Integer> set = Set.of();
      • 初始化一个空的,不可变的Set<Integer>
    • Set<Integer> set = Set.of(1);
      • 使用一个元素初始化不可变Set<Integer>
    • Set<Integer> set = Set.of(1, 2);
      • 使用两个元素初始化不可变Set<Integer>
    • Set<Integer> set = Set.of(1, 2, 3, 4, 5, ...);
      • 使用可变数量的元素初始化不可变Set<Integer>
  • Map<Integer, Integer>
    • Map<Integer, Integer> map = Map.of();
      • 初始化一个空的,不可变的Map<Integer, Integer>
    • Map<Integer, Integer> map = Map.of(1, 2);
      • 使用一个键值条目初始化不可变Map<Integer, Integer>
      • 请注意,密钥为1,值为2
    • Map<Integer, Integer> map = Map.of(1, 2, 3, 4);
      • 使用两个键值条目初始化不可变Map<Integer, Integer>
      • 请注意,密钥为13,值为24
    • Map<Integer, Integer> map = Map.ofEntries(Map.entry(1, 2), Map.entry(3, 4), ...);
      • 使用可变数量的键值条目初始化不可变Map<Integer, Integer>

正如您所看到的,这种新的初始化方法需要的代码少于其前辈。

我可以使用集合工厂方法创建可变对象吗?

由集合工厂方法创建的Collection<E>本质上是不可变的,但是我们能够将它们传递给Collection<E>的实现的构造函数以生成可变版本:

  • List<Integer>
    • List<Integer> mutableList = new ArrayList<>(List.of(1, 2, 3, 4, 5));
  • Set<Integer>
    • Set<Integer> mutableSet = new HashSet<>(Set.of(1, 2, 3, 4, 5));
  • Map<Integer, Integer>
    • Map<Integer, Integer> mutableMap = new HashMap<>(Map.of(1, 2, 3, 4));