📜  Java 8 流(1)

📅  最后修改于: 2023-12-03 15:31:28.302000             🧑  作者: Mango

Java 8 流

Java 8引入了Stream API,它允许开发人员通过一系列操作来处理集合和数组。Stream是一种高效、功能强大和可组合的API,已被很多Java程序员广泛应用。让我们看看它的基本概念和用法。

什么是流

流是一种实现了序列化操作的对象集合。它可以来自任何数据源,例如集合、数组、I/O通道等。Stream API不会改变原始数据源。它们会转换操作的结果,并执行操作后生成一个新的Stream对象。

Stream操作可以使用Parallel Stream或Sequential Stream两种方式执行,前者利用了多线程来加速操作,后者则按照原始顺序执行操作。

Stream的创建

创建Stream对象可以通过如下的方式:

// 从集合创建
Stream<String> stream1 = list.stream();
// 从数组创建
Stream<Integer> stream2 = Arrays.stream(array);
// 使用Stream.of()方法创建
Stream<String> stream3 = Stream.of("a", "b", "c");
// 创建一个空的Stream对象
Stream<Object> emptyStream = Stream.empty();
Stream的中间操作

Stream的中间操作是指操作结果是另一个Stream对象的操作。它们不会对原始数据源造成任何影响。我们可以进行如下的中间操作:

1. filter()

该操作使用一个谓词函数来过滤集合中的元素。它的签名如下:

Stream<T> filter(Predicate<? super T> predicate)
// 从集合中过滤出长度大于3的字符串
List<String> list = Arrays.asList("apple","banana","cherry","peach");
Stream<String> stream = list.stream().filter(str -> str.length() > 3);
2. map()

该操作利用一个函数将集合中的元素进行映射处理。它的签名如下:

<R> Stream<R> map(Function<? super T,? extends R> mapper)
// 对集合中每个元素进行平方处理
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream().map(i -> i * i);
3. flatMap()

该操作类似于map,但是它会对集合中的每个元素产生一个Stream对象,然后再将所有的Stream对象组合成一个Stream。它的签名如下:

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
// 对集合中每个字符串进行字符拆分处理
List<String> list = Arrays.asList("apple","banana","cherry","peach");
Stream<String[]> stream1 = list.stream().map(str -> str.split(""));
Stream<String> stream2 = list.stream().flatMap(str -> Arrays.stream(str.split("")));
4. sorted()

该操作对Stream中元素进行排序。它的签名如下:

Stream<T> sorted()
// 对集合中的元素进行排序处理
List<Integer> list = Arrays.asList(5, 2, 1, 3, 4);
Stream<Integer> stream = list.stream().sorted();
5. distinct()

该操作用于去重。它的签名如下:

Stream<T> distinct()
// 对集合中的元素进行去重处理
List<Integer> list = Arrays.asList(1, 2, 1, 3, 4);
Stream<Integer> stream = list.stream().distinct();
6. peek()

该操作用于向Stream中的每个元素施加一个操作,但不会影响元素的类型和值。它的签名如下:

Stream<T> peek(Consumer<? super T> action)
// 对集合中的元素进行打印处理
List<String> list = Arrays.asList("apple","banana","cherry","peach");
Stream<String> stream = list.stream().peek(System.out::println);
7. limit()

该操作用于从Stream中取出前n个元素。它的签名如下:

Stream<T> limit(long maxSize)
// 对集合中的元素取出前3个
List<String> list = Arrays.asList("apple","banana","cherry","peach");
Stream<String> stream = list.stream().limit(3);
8. skip()

该操作用于从Stream中跳过前n个元素。它的签名如下:

Stream<T> skip(long n)
// 对集合中的元素跳过前2个
List<String> list = Arrays.asList("apple","banana","cherry","peach");
Stream<String> stream = list.stream().skip(2);
Stream的终端操作

Stream的终端操作是指操作结果不是另一个Stream对象的操作。它们会生成一个结果或者一个副作用。我们可以进行如下的终端操作:

1. forEach()

该操作用于对Stream中的元素施加一个操作,操作是一个Consumer类型的接口。它的签名如下:

void forEach(Consumer<? super T> action)
// 对集合中的元素进行打印处理
List<String> list = Arrays.asList("apple","banana","cherry","peach");
list.stream().forEach(System.out::println);
2. toArray()

该操作用于将Stream中的元素转化为数组。它的签名如下:

Object[] toArray()
<T> T[] toArray(T[] a)
// 将集合中的元素转化为数组
List<String> list = Arrays.asList("apple","banana","cherry","peach");
String[] arr1 = list.stream().toArray(String[]::new);
Object[] arr2 = list.stream().toArray();
3. reduce()

该操作用于通过将流中所有元素进行逐个处理,生成一个最终的结果。它的签名如下:

T reduce(T identity, BinaryOperator<T> accumulator)
Optional<T> reduce(BinaryOperator<T> accumulator)
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
// 计算集合中所有元素的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
int sum = list.stream().reduce(0, Integer::sum);
Optional<Integer> optionalSum = list.stream().reduce(Integer::sum);
4. collect()

该操作用于将Stream中的元素收集到集合中。它的签名如下:

<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
<R,A> R collect(Collector<? super T,A,R> collector)
// 将集合中的元素收集到Set中
List<String> list = Arrays.asList("apple","banana","cherry","peach");
Set<String> set = list.stream().collect(Collectors.toSet());
5. count()

该操作用于计算Stream中元素的个数。它的签名如下:

long count()
// 计算集合中元素的个数
List<String> list = Arrays.asList("apple","banana","cherry","peach");
long count = list.stream().count();
6. findFirst()

该操作用于取得Stream中的第一个元素。它的签名如下:

Optional<T> findFirst()
// 取得集合中的第一个元素
List<String> list = Arrays.asList("apple","banana","cherry","peach");
Optional<String> first = list.stream().findFirst();
7. anyMatch()

该操作用于判断Stream中是否有满足给定条件的元素。它的签名如下:

boolean anyMatch(Predicate<? super T> predicate)
// 判断集合中是否有满足条件的元素
List<String> list = Arrays.asList("apple","banana","cherry","peach");
boolean flag = list.stream().anyMatch(str -> str.contains("a"));
Conclusion

Stream API为Java程序员提供了一个强大的工具,可以非常方便地处理集合和数组。它具有高度的可组合性和减少代码量的优势,并支持并行处理以提高性能。我们应该熟练掌握Stream API,为我们的开发工作带来更高效的编程体验。