我们经常使用 Stream API 最后都会进行重新组装成一个 List,例如下面的代码:
public class StreamTest { @Test void test() { List<String> list = List.of("ABC", "ACD", "BCD", "CCE"); List<String> result = list.stream() .filter(e -> e.contains("D")) .collect(Collectors.toList()); System.out.println(result); } }
上面这是 Java8 的写法,在 Java 16 中可以将最后的 .collect(Collectors.toList()); 进行简化,例如:
public class StreamTest { @Test void test() { List<String> list = List.of("ABC", "ACD", "BCD", "CCE"); List<String> result = list.stream() .filter(e -> e.contains("D")) .toList(); System.out.println(result); } }
这个方法是 Java 16 才支持的一个方法,它可以直接将 Stream 转化成 List。
就完整上面的代码逻辑,这样的替换完全是可以的,但是虽然最终都转成 List 了,他们之间是否还有区别呢?
这里我单独拉出来说,显然肯定是有区别的。
通过查看 Stream.toList() 的源码:
default List<T> toList() { return (List<T>) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray()))); }
我们可以发现,它所创建的是一个 unmodifiableList 不可变的 List。
而使用 Stream.collect(Collectors.toList()) 创建出来的则是一个普通的 List,是可以做增删改操作的。
那么如果用 Collectors 也要创建不可变的 List 要怎么写呢?其实也很简单,只需要调用 Collectors.toUnmodifiableList() 就可以了。
public class StreamTest { @Test void test() { List<String> list = List.of("ABC", "ACD", "BCD", "CCE"); List<String> result = list.stream() .filter(e -> e.contains("D")) .collect(Collectors.toUnmodifiableList()); System.out.println(result); } }
但要注意的是,这个方法 Java 8 里也没有,是 Java 10 才开始支持的。
Stream.toList()的性能要各方面都要好于Collectors.toList()和Collectors.toUnmodifiableList()。
