Java Stream介绍及基本用法解析

1. 什么是Java Stream

  • 1.1 Stream概念介绍

Java Stream是Java 8中引入的一种处理集合的新方式,它可以让开发者以一种类似于SQL语句的声明方式来操作集合,提供了一种高效且便捷的数据处理方式。Stream使用函数式编程的思想,可以大大简化集合数据的处理过程,使代码更加简洁和易读。

  • 1.2 Stream和Collection的区别

Stream 和 Collection 是Java中处理集合数据的两种机制,它们之间有以下几点区别:
- Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。
- Collection 提供了存储和访问数据的方式,而 Stream 本身不存储数据,它只是描述对数据的运算。
- Collection 是数据结构,Stream 是对这些数据的操作。
- Collection 是同步的,它会阻塞操作,而 Stream 是异步的,它可以并行执行。

2. 创建Stream

  • 2.1 从集合创建Stream

通过集合类的 stream() 方法,可以轻松地将集合转换为一个 Stream 来进行各种操作。

List<String> list = Arrays.asList("apple", "banana", "orange", "grape");
Stream<String> stream = list.stream();
  • 2.2 通过Stream静态工厂方法创建Stream

除了从集合创建Stream,我们还可以使用 Stream 的静态工厂方法来创建Stream,比如 Stream.of() 方法。

Stream<String> streamOf = Stream.of("apple", "banana", "orange", "grape");

通过上面两种方式,我们可以方便地创建一个 Stream 对象,为接下来的操作做准备。

总结

Java Stream 中,我们可以通过集合类的 stream() 方法或者 Stream 的静态工厂方法来创建 Stream 对象,以便进行后续的操作。这些方法提供了方便快捷地创建 Stream 的途径,使得数据处理更加高效。

简单的创建Stream流程示意图

graph LR
A[创建集合] --> B(集合.stream())
C[直接静态方法创建] --> D(Stream.of())
B --> E(获取Stream)
D --> E
E --> F[后续操作]

通过以上 Stream 创建的方式,我们可以在开始阶段就轻松获取到数据处理所需的 Stream 对象,为后续的操作打下良好的基础。

3. Stream中的中间操作

在Java Stream中,中间操作是对Stream进行一系列连续操作的过程,这些操作会返回一个新的Stream对象。这一章节将介绍Stream中的几种常用中间操作,并给出相应的示例代码和示意图。

  • 3.1 Filter(过滤)

Filter操作可以根据指定的条件过滤出Stream中符合条件的元素。

示例代码:

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

List<Integer> filteredList = numbers.stream()
                                    .filter(num -> num % 2 == 0)
                                    .collect(Collectors.toList());

System.out.println(filteredList);

结果说明:上述代码中,通过Filter操作筛选出了列表中的偶数元素,最终输出结果为[2, 4, 6, 8, 10]。

  • 3.2 Map(映射)

Map操作可以对Stream中的每个元素进行映射转换操作。

示例代码:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

List<Integer> nameLengths = names.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());

System.out.println(nameLengths);

结果说明:上述代码利用Map操作将字符串列表中的每个元素转换为其长度,最终输出结果为[5, 3, 7]。

  • 3.3 Sorted(排序)

Sorted操作可以对Stream中的元素进行排序操作。

示例代码:

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

List<Integer> sortedList = numbers.stream()
                                  .sorted()
                                  .collect(Collectors.toList());

System.out.println(sortedList);

结果说明:上述代码通过Sorted操作将列表中的元素进行升序排序,最终输出结果为[1, 1, 2, 3, 3, 4, 5, 5, 6, 9]。

  • 3.4 Limit(截取)

Limit操作可以对Stream进行截取操作,限制返回的元素个数。

示例代码:

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

List<Integer> limitedList = numbers.stream()
                                   .limit(5)
                                   .collect(Collectors.toList());

System.out.println(limitedList);

结果说明:上述代码通过Limit操作限制返回前5个元素,最终输出结果为[1, 2, 3, 4, 5]。

以上是Stream中的几种常用中间操作,它们可以灵活结合以实现对数据的多种处理和转换操作。通过这些中间操作,我们可以方便地对数据进行筛选、转换、排序和截取等处理。

4. Stream中的终端操作

在Java Stream中,终端操作是指当流经过所有的中间操作后,需要对流执行的最终操作。终端操作会触发流的遍历与处理,生成最终的结果。在本章中,我们将详细介绍几种常见的Stream终端操作及其用法。

4.1 forEach

在Stream中,forEach是一种常见的终端操作,用于对流中的每个元素执行指定的操作。例如,我们有一个整数列表,我们可以使用forEach来输出每个元素的平方值:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

numbers.stream()
       .map(num -> num * num)
       .forEach(System.out::println);

在上面的代码中,我们首先将列表中的每个元素进行平方操作,然后使用forEach输出每个元素的平方值。

4.2 collect

另一个常见的终端操作是collect,它将流中的元素收集起来并返回一个新的集合。我们可以使用collect来将流中的元素收集到一个列表中:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

List<String> filteredNames = names.stream()
                                  .filter(name -> name.length() > 4)
                                  .collect(Collectors.toList());

// 输出筛选后的名字列表
filteredNames.forEach(System.out::println);

在上面的代码中,我们筛选出长度大于4的名字,并将它们收集到一个新的列表filteredNames中。

4.3 reduce

reduce操作可以将流中的所有元素归约成一个结果。例如,我们可以使用reduce来计算列表中所有元素的和:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = numbers.stream()
                 .reduce(0, (a, b) -> a + b);

System.out.println("Sum of numbers: " + sum);

在上面的代码中,我们使用reduce对列表中的所有元素进行求和操作,初始值为0。

通过这些终端操作,我们可以对Stream进行处理并得到我们想要的结果,从而实现更加灵活和高效的数据处理操作。

开始
中间操作
中间操作
中间操作
终端操作
结果处理

以上就是Java Stream中的终端操作的介绍,通过合理使用这些终端操作,我们可以更好地利用Stream来处理数据,提高代码的可读性和易维护性。

5. Stream并行处理

在Java Stream中,通过并行处理可以充分利用多核系统的优势,提高处理大数据集合时的效率。本章将介绍如何创建并行Stream以及并行Stream与顺序Stream的比较。

5.1 并行Stream的创建

在Java中,可以通过parallel()方法将一个顺序Stream转换为并行Stream,示例如下:

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

// 顺序Stream
Stream<Integer> sequentialStream = numbers.stream();

// 并行Stream
Stream<Integer> parallelStream = numbers.parallelStream();

通过parallel()方法,我们可以轻松地将顺序Stream转换为并行Stream,从而利用多线程并发处理数据。

5.2 并行Stream与顺序Stream的比较

并行Stream与顺序Stream的主要区别在于数据处理的方式。在顺序Stream中,数据是按照插入顺序依次处理的,而在并行Stream中,数据会被分配到多个线程上并行处理,最后再将结果合并。

下表对比了并行Stream和顺序Stream的特点:

特点顺序Stream并行Stream
处理方式依次处理每个元素并行处理多个元素
运行效率适用于小规模数据集合适用于大规模数据集合,利用多核处理器提高效率
线程安全性线程安全需要注意线程安全性,可能需要同步操作
可控性相对简单易控制并行处理需要考虑线程安全、性能消耗等方面的因素

通过选择合适的Stream类型,可以根据实际场景提高数据处理效率。需要根据数据规模、数据处理复杂度等因素来选择使用顺序Stream还是并行Stream。

结论

并行Stream是Java中用于并行处理数据集合的重要工具,可以充分利用多核处理器的优势,提高数据处理效率。在实际开发中,根据数据规模和处理性能需求来选择合适的Stream类型,以达到最佳的数据处理效果。

6.1 数据筛选与转换

在实际开发中,经常需要对数据进行筛选和转换操作。通过Java Stream,我们可以轻松实现这些功能。下面我们来看一个简单的场景,筛选出集合中大于10的元素,并将它们转换成对应的平方值。

List<Integer> numbers = Arrays.asList(5, 12, 3, 18, 9, 7, 15);

List<Integer> squaredNumbers = numbers.stream()
                                      .filter(num -> num > 10)
                                      .map(num -> num * num)
                                      .collect(Collectors.toList());

System.out.println("大于10的数对应的平方值: " + squaredNumbers);

通过上面的代码,我们首先筛选出集合中大于10的元素,然后将这些元素转换成对应的平方值,最后将结果收集到一个新的列表中并输出。这展示了如何通过Stream实现数据的筛选与转换。

6.2 数据聚合与统计

除了对数据进行筛选与转换外,Java Stream还提供了丰富的方法来实现数据的聚合与统计功能。下面我们来看一个实际场景,计算集合中所有元素的平均值。

List<Integer> scores = Arrays.asList(80, 90, 75, 95, 85);

Double average = scores.stream()
                       .mapToDouble(Integer::doubleValue)
                       .average()
                       .orElse(0);

System.out.println("平均分数为: " + average);

在上面的示例中,我们先将集合中的整数转换为double类型,然后调用average方法计算平均值,并使用orElse方法处理空集合的情况,最终输出平均分数。

6.3 数据分组与分区

除了基本的数据操作外,Java Stream还可以实现数据的分组和分区。下面我们来看一个场景,根据学生成绩将学生分为及格和不及格两组。

List<Student> students = Arrays.asList(
        new Student("Alice", 85),
        new Student("Bob", 60),
        new Student("Charlie", 75),
        new Student("David", 45),
        new Student("Eva", 90)
);

Map<Boolean, List<Student>> passMap = students.stream()
        .collect(Collectors.partitioningBy(s -> s.getScore() >= 60));

System.out.println("及格学生: " + passMap.get(true));
System.out.println("不及格学生: " + passMap.get(false));

通过以上代码,我们利用partitioningBy方法根据学生成绩及格与否将学生分为两组,并最终输出结果。这展示了如何利用Stream实现数据的分组与分区功能。

通过以上示例,我们可以看到Java Stream在数据处理方面的强大之处。从数据筛选转换到数据统计聚合再到数据分组分区,Stream提供了丰富的方法满足各种数据处理需求。深入学习和灵活运用Stream,将会极大提升代码的简洁性和可读性。

  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java StreamJava 8 中新增的一个 API,用于处理集合数据。它提供了一种更加简洁、高效的方式来操作集合,可以让代码更加简洁、易读、易维护。下面是 Java Stream基本使用方法: 1. 创建流 Java Stream 可以从多种数据源中创建,比如集合、数组、文件等。例如,从集合创建一个 Stream 可以使用以下代码: ```java List<String> list = new ArrayList<>(); Stream<String> stream = list.stream(); ``` 2. 中间操作 中间操作是指对 Stream 进行操作,返回一个新的 Stream。常见的中间操作包括:filter、map、sorted、distinct 等。例如,下面的代码使用 filter 操作过滤出长度大于 5 的字符串: ```java List<String> list = Arrays.asList("apple", "banana", "orange", "watermelon"); Stream<String> stream = list.stream().filter(s -> s.length() > 5); ``` 3. 终止操作 终止操作是指对 Stream 进行最终的操作,返回一个非 Stream 的结果。常见的终止操作包括:forEach、reduce、collect、count 等。例如,下面的代码使用 forEach 操作输出过滤后的字符串: ```java List<String> list = Arrays.asList("apple", "banana", "orange", "watermelon"); list.stream().filter(s -> s.length() > 5).forEach(System.out::println); ``` 4. 短路操作 短路操作是指对 Stream 进行操作时,只要满足一定条件就可以停止操作,不必对整个流进行操作。常见的短路操作包括:findFirst、findAny、allMatch、anyMatch、noneMatch 等。例如,下面的代码使用 findAny 操作找到第一个长度大于 5 的字符串: ```java List<String> list = Arrays.asList("apple", "banana", "orange", "watermelon"); Optional<String> result = list.stream().filter(s -> s.length() > 5).findAny(); ``` 以上就是 Java Stream基本使用方法,需要注意的是,Stream 是一次性的,一旦进行了终止操作,就不能再对该 Stream 进行操作。同时,Stream 也是惰性求值的,只有在终止操作时才会进行真正的计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成熟的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值