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

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

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

注1:为了防止使用原始类型,我选择为下面提到的每个类提供一个generics类型,使用E代表Collection一个元素。

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

什么是收集工厂方法?

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

作为不可变的,在初始化之后, Collection不能添加,删除或修改元素。

使用Java 9,为以下接口提供了集合工厂方法: ListSetMap

它们有什么改进?

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

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

我为什么要用它们?

我认为集合工厂方法为开发人员提供了一个简洁的方法,用初始元素/键值条目初始化ListSetMap ,这可以通过下面的例子看到。

使用的正确语法是什么?

为简单起见,这些示例将用Integer替换generics类型EKV

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

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

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

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

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