java9新特性-新增只读集合和工厂方法

java 9 List,Set 和 Map 接口中,新的静态工厂方法可以创建这些集合的不可变实例。

这些工厂方法可以以更简洁的方式来创建集合。

旧方法创建

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Tester {
public static void main(String []args) {
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");
set = Collections.unmodifiableSet(set);
System.out.println(set);
List<String> list = new ArrayList<>();

list.add("A");
list.add("B");
list.add("C");
list = Collections.unmodifiableList(list);
System.out.println(list);
Map<String, String> map = new HashMap<>();

map.put("A","Apple");
map.put("B","Boy");
map.put("C","Cat");
map = Collections.unmodifiableMap(map);
System.out.println(map);
}
}

Java 8 创建不可变集合

在 Java 9 之前要创建一个只读集合,通常需要通过将可变集合转换为不可变集合的方式来实现,即使用Collections.unmodifiableXXX(),其中XXX可以是List、Set或Map,例如要创建一个只读 List:

@Test
public void test() {
List<String> list = new ArrayList<>();
list.add("死磕 Java 新特性");
list.add("死磕 Netty");

// 转换为只读集合
list = Collections.unmodifiableList(list);
}

使用 Collections.unmodifiableList() 将 List 转换为不可变集合,如果我们使用 add() 来添加元素,会报 UnsupportedOperationException 异常信息
这种方式虽然有效,但是比较麻烦,它需要额外的步骤来处理,而且容易出错

Java 9 创建不可变集合

为了解决 Java 8 的问题,Java 9 引入不可变集合和对应的工厂方法,目的就在于提供更安全、更高效的方式来创建不可变集合,同时确保原始集合无法被修改。

static <E> List<E> of(E e1, E e2, E e3);
static <E> Set<E> of(E e1, E e2, E e3);
static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3);
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>... entries)
  • List 和 Set 接口, of(…) 方法重载了 0 ~ 10 个参数的不同方法 。

  • Map 接口, of(…) 方法重载了 0 ~ 10 个参数的不同方法 。

  • Map 接口如果超过 10 个参数, 可以使用 ofEntries(…) 方法。

看到这么多重载方法是不是有点儿懵逼,感觉是不是只需要有 of() 和 of(E… elements) 这两个方法就可以了,从实现的效果上来说,确实是可以。of(E… elements) 确实是一个非常灵活的方法,可以适用于多种情况,但是Java 9 引入多个重载的 List.of() 方法并不是为了提供不同数量的参数选择的灵活性,而是为了性能和可读性的考虑。每个 List.of()方法的重载版本都是针对特定的参数数量进行了优化,以提高性能和代码清晰度。当使用 of(E… elements) 时,Java运行时需要创建一个数组以容纳传递的元素(Java 的可变参数,会被编译器转型为一个数组),这可能会引入一些额外的开销,尤其是在创建小型 List 时。而多个重载的 List.of() 方法避免了这种开销,因为它们直接接受参数,而无需创建数组。所以,看着懵逼,但是性能杠杠的

不可变的 List 特征

  • 这些列表是不可变的。调用任何改变 List 的方法(如add()、remove()、replaceAll()、clear()),都会抛出 UnsupportedOperationException

  • 它们不允许 null 元素。 尝试添加 null 元素将导致 NullPointerException

  • 列表中元素的顺序与提供的参数或提供的数组中的元素的顺序相同

实例

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.AbstractMap;
import java.util.Map;
import java.util.Set;

public class Tester {

public static void main(String []args) {
Set<String> set = Set.of("A", "B", "C");
System.out.println(set);
List<String> list = List.of("A", "B", "C");
System.out.println(list);
Map<String, String> map = Map.of("A","Apple","B","Boy","C","Cat");
System.out.println(map);

Map<String, String> map1 = Map.ofEntries (
new AbstractMap.SimpleEntry<>("A","Apple"),
new AbstractMap.SimpleEntry<>("B","Boy"),
new AbstractMap.SimpleEntry<>("C","Cat"));
System.out.println(map1);
}
}