详解JAVA Stream

目录

1.概述

2.流的创建

3.中间操作

3.1.清单

3.2.filter

3.3.map

3.4.flatMap

3.5.distinct

3.6.sorted

3.7.peek

3.8.limit

3.9.skip

4.中止操作

4.1.清单

4.2.非短路操作

4.2.1.forEach

4.2.2.count

4.2.3.reduce

4.2.4.collect

4.2.5.max、min

4.3.短路操作

4.3.1.findFrist

4.3.2.findAny

4.3.3.allMatch

4.3.4.anyMatch

4.3.5.noneMatch

5.并行流


1.概述

Java Stream是Java 8引入的一种新特性,用于简化集合类的数据处理和操作。Stream API提供了一种流式处理的方式,可以对数据进行过滤、映射、聚合等操作,使得数据处理更加简洁、高效和易于理解。

stream中对数据的操作分为两类:

  • 中间操作,对流的中间操作,即从流中取流。
  • 中止操作,对流的最终操作,即从流中取值。

两种操作的代码示例:

int[] nums={1,2,3};
//map,中间操作,返回的是流
//sum,中止操作,返回的是最终结果
int sum= IntStream.of(nums).map(i->i*2).sum();
System.out.println(sum);

需要注意的一点是:中间操作都是惰性的,中止操作出现,才会真正执行中间操作。

以上面的例子来说,map操作虽然被率先调用了,但是在sum操作调用之前map操作其实是没有被执行的,sum操作调用后map才会执行。

2.流的创建

JDK8开始,JDK中带有多种创建stream的API:

//从集合中创建
List<String> list=new ArrayList<>();
list.stream();
list.parallelStream();
//从数组创建
Arrays.stream(new int[]{1,2,3});
//创建数字流
IntStream.of(1,2,3);
//创建无限流(根据传入的参数,截取指定长度)
new Random().ints().limit(10);

3.中间操作

3.1.清单

stream的中间操作,本质上就是对流进行加工,返回的是操作后的stream。

中间操作分为两种:

  • 有状态,依赖于其他中间操作,必须等所依赖的其他中间操作完成后,才可执行。如排序,必须等所有其他还在进行的中间操作完成,才能进行排序。
  • 无状态,不依赖于其他中间操作,自己玩自己的就行。

3.2.filter

filter(Predicate<T> predicate):根据给定的Predicate函数来过滤Stream中的元素。

List<Integer> list = Arrays.asList(1,2,3,4,5);
List<Integer> result = list.stream().filter(x -> x%2==0).collect(Collectors.toList());
// 输出结果为[2, 4]

3.3.map

map(Function<T, R> mapper):对Stream中的每个元素应用一个函数,返回一个新的Stream对象。

List<String> list = Arrays.asList("apple", "banana", "orange");
List<Integer> result = list.stream().map(x -> x.length()).collect(Collectors.toList());
// 输出结果为[5, 6, 6]

3.4.flatMap

flatMap(Function<T, Stream<R>> mapper):对Stream中的每个元素应用一个函数,将每个元素映射为一个新的Stream对象,然后将所有新的Stream对象合并成一个新的Stream对象。

List<List<Integer>> list = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6));
List<Integer> result = list.stream().flatMap(x -> x.stream()).collect(Collectors.toList());
// 输出结果为[1, 2, 3, 4, 5, 6]

3.5.distinct

distinct():去除Stream中的重复元素。

List<Integer> list = Arrays.asList(1, 2, 2, 3, 3, 4, 4, 5);
List<Integer> result = list.stream().distinct().collect(Collectors.toList());
// 输出结果为[1, 2, 3, 4, 5]

3.6.sorted

sorted():对Stream中的元素进行排序。

List<Integer> list = Arrays.asList(4, 2, 1, 3, 5);
List<Integer> result = list.stream().sorted().collect(Collectors.toList());
// 输出结果为[1, 2, 3, 4, 5]

3.7.peek

peek(Consumer<T> action):对Stream中的每个元素应用一个Consumer函数,返回一个新的Stream对象,与map类似,但是它不会改变元素的值。

List<Integer> list = Arrays.asList(1, 2, 3);
List<Integer> result = list.stream().peek(x -> x = x + 1).collect(Collectors.toList());
// 输出结果为[1, 2, 3]

3.8.limit

limit(long maxSize):截取Stream中的前maxSize个元素。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream().limit(3).collect(Collectors.toList());
// 输出结果为[1, 2, 3]

3.9.skip

skip(long n):跳过Stream中的前n个元素。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = list.stream().skip(3).collect(Collectors.toList());
// 输出结果为[4, 5]

4.中止操作

4.1.清单

在Java Stream API中,中止操作可以分为短路操作和非短路操作,它们的区别在于短路操作是最后一个操作,后面无法再跟任何操作,非短路操作后面还可以跟其他操作。

4.2.非短路操作

4.2.1.forEach

此操作可以迭代Stream中的每个元素,并对其进行操作。

List<String> list = Arrays.asList("Java", "is", "cool");
list.stream()
    .forEach(System.out::println);

4.2.2.count

此操作可以返回Stream中元素的数量。

List<String> list = Arrays.asList("Java", "is", "cool");
long count = list.stream()
                .filter(s -> s.length() > 2)
                .count();
System.out.println(count);

4.2.3.reduce

此操作可以将Stream中的所有元素合并到一个结果中。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = list.stream()
                    .reduce((a, b) -> a + b);
System.out.println(result.get());

4.2.4.collect

此操作可以将Stream中的元素收集到一个集合中。

List<String> list = Arrays.asList("Java", "is", "cool");
List<String> result = list.stream()
                        .collect(Collectors.toList());
System.out.println(result);

4.2.5.max、min

此操作可以返回Stream中的最大或最小元素。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> max = list.stream()
                            .max(Integer::compareTo);
System.out.println(max.get());

4.3.短路操作

4.3.1.findFrist

返回Stream中的第一个元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstEven = numbers.stream()
                                      .filter(n -> n % 2 == 0)
                                      .findFirst();
if (firstEven.isPresent()) {
    System.out.println("The first even number is " + firstEven.get());
} else {
    System.out.println("No even numbers found.");
}

4.3.2.findAny

findFirst()相似,findAny()也返回Stream中的一个元素,但是这个元素可以是任意一个,而不一定是第一个。在并行Stream中,findAny()可能会返回任何一个符合条件的元素。与findFirst()不同的是,findAny()不保证返回的元素是Stream中的第一个符合条件的元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> anyEven = numbers.stream()
                                    .filter(n -> n % 2 == 0)
                                    .findAny();
if (anyEven.isPresent()) {
    System.out.println("An even number is " + anyEven.get());
} else {
    System.out.println("No even numbers found.");
}

4.3.3.allMatch

allMatch(Predicate<T> predicate):判断Stream中的所有元素是否都满足给定的Predicate条件。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEven = numbers.stream()
                         .allMatch(n -> n % 2 == 0);
if (allEven) {
    System.out.println("All numbers are even.");
} else {
    System.out.println("Some numbers are not even.");
}

4.3.4.anyMatch

anyMatch(Predicate<T> predicate):判断Stream中是否存在任意一个元素满足给定的Predicate条件。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean anyEven = numbers.stream()
                         .anyMatch(n -> n % 2 == 0);
if (anyEven) {
    System.out.println("At least one number is even.");
} else {
    System.out.println("No even numbers found.");
}

4.3.5.noneMatch

noneMatch(Predicate<T> predicate):判断Stream中是否没有任何元素满足给定的Predicate条件。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean noneNegative = numbers.stream()
                              .noneMatch(n -> n < 0);
if (noneNegative) {
    System.out.println("All numbers are non-negative.");
} else {
    System.out.println("Some numbers are negative.");
}

5.并行流

Java Stream提供了一种流式处理的方式,可以快速、方便地对集合、数组等数据进行处理和操作。而并行流则是Java Stream中的一种特殊类型的流,它可以自动将Stream中的数据分成多个小块,并在多个处理器上并行处理这些小块,以提高处理效率。

在Java 8之前,Java只能使用线程来实现并发编程。使用线程编程虽然可以实现并发执行,但是需要程序员自己管理线程的创建、调度和同步等问题,很容易引入死锁、竞争条件等问题。而在Java 8中引入了Stream API和并行流,使得并发编程变得更加容易和高效。

使用并行流的方式非常简单,只需要在创建Stream时调用parallel()方法,就可以将Stream转换为并行流,如下所示:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

List<Integer> result = numbers.parallelStream() // 创建并行流
                               .map(n -> n * n) // 对每个元素进行平方运算
                               .collect(Collectors.toList()); // 将结果收集到列表中

System.out.println(result);

在上面的示例中,使用parallelStream()方法创建一个并行流,并使用map()方法对每个元素进行平方运算,最后使用collect()方法将结果收集到一个列表中。

当列表中的元素数量很大时,使用并行流可以显著提高运行效率,因为并行流可以在多个处理器上并行处理元素。同时,Java Stream API的设计也保证了在并行执行时,Stream的操作是线程安全的,不需要程序员自己进行线程同步。

猜你喜欢

转载自blog.csdn.net/Joker_ZJN/article/details/129648877