java的stream流知识点总结

系列文章目录


一、什么是stream流

Stream 是 Java 8 引入的一种新方式,目的是帮助我们更简洁、更高效地处理集合(如 List、Set、Map 等)。你可以把 Stream 想象成一条“流水线”,数据就像是流水线上的原材料,经过流水线的各个环节处理,最后你会得到想要的结果

1. 为什么要使用 Stream?

查看
在没有 Stream 之前,处理集合数据时,我们通常会使用 循环 来逐个操作每个元素,这样代码冗长、难以维护。
传统做法
假设我们有一个 List 存储了多个整数,我们想找出所有大于 10 的数字。

List<Integer> numbers = Arrays.asList(5, 12, 15, 8, 22);
List<Integer> result = new ArrayList<>();
 
for (int num : numbers) {
    if (num > 10) {
        result.add(num);
    }
}
System.out.println(result);  // 输出 [12, 15, 22]

这种方式看起来没问题,但是如果我们需要对多个集合执行各种复杂的操作(过滤、排序、映射等),代码就会变得非常冗长。
使用 Stream
Stream 让你可以通过一系列简单的“流式操作”来处理数据。

List<Integer> numbers = Arrays.asList(5, 12, 15, 8, 22);
List<Integer> result = numbers.stream()  // 将 List 转换成 Stream
                              .filter(num -> num > 10)  // 过滤大于 10 的元素
                              .collect(Collectors.toList());  // 收集结果为一个新的 List
 
System.out.println(result);  // 输出 [12, 15, 22]

通过 stream() 方法,我们将 List 转换成了一个 Stream,接着使用了 filter() 来过滤出大于 10 的元素,最后通过 collect() 方法将结果转回 List

2. 流(Stream)的核心特点

1.声明式代码:你不需要关心具体的如何循环,Stream 把这些细节帮你处理了,你只需要专注于“做什么”而不是“怎么做”。
2.支持链式调用:你可以将多个操作连接在一起,像流水线一样一步步处理数据。
3. 惰性求值:Stream 中的操作不会立即执行,直到你调用终端操作时,才会真正执行所有的操作。
4. 可以并行处理:Stream 使得并行处理变得非常简单,特别适用于大数据量的处理。

3. 流(Stream)的核心特点Stream 的基本操作

Stream 主要有两类操作:中间操作 和 终端操作。

  1. 中间操作(Intermediate Operations)
    中间操作会返回一个新的 Stream,这意味着你可以连续链式调用多个中间操作。中间操作通常是懒执行的,只有在终端操作执行时,所有的中间操作才会一起执行。

常用的中间操作包括:

  • filter():过滤数据,返回符合条件的元素。
  • map():将每个元素转换成新的形式。
  • sorted():对数据进行排序

示例

List<Integer> numbers = Arrays.asList(5, 12, 15, 8, 22);
 
List<Integer> result = numbers.stream()        // 将 List 转换为 Stream
                              .filter(num -> num > 10)  // 过滤出大于 10 的元素
                              .map(num -> num * 2)      // 每个数字乘以 2
                              .sorted()                 // 排序
                              .collect(Collectors.toList());  // 收集结果为一个 List
 
System.out.println(result);  // 输出 [24, 30, 44]

在这个例子中,我们做了三件事:

  • 先过滤出大于 10 的数字。
  • 然后将每个数字乘以 2。
  • 最后对结果进行排序。
  1. 终端操作(Terminal Operations)
    终端操作是 Stream 处理的最后一步,执行完终端操作后,Stream 就会被消耗掉,无法继续使用。常见的终端操作有:
  • collect():将 Stream 中的元素收集成一个集合。
  • forEach():对每个元素执行某个操作。
  • reduce():将 Stream 中的所有元素聚合成一个结果(比如求和)。
  • count():统计元素的数量。

示例:

List<Integer> numbers = Arrays.asList(5, 12, 15, 8, 22);
 
// 1. collect():收集到 List 中
List<Integer> result = numbers.stream()
                              .filter(num -> num > 10)
                              .collect(Collectors.toList());
System.out.println(result);  // 输出 [12, 15, 22]
 
// 2. forEach():打印每个元素
numbers.stream()
       .forEach(num -> System.out.println(num));
 
// 3. reduce():求和
int sum = numbers.stream()
                 .reduce(0, (a, b) -> a + b);
System.out.println(sum);  // 输出 62

5. 延迟执行与惰性求值

Stream 的操作是惰性执行的,也就是说,Stream 中的操作并不会立即执行,而是等到你真正需要结果时(调用终端操作)才会执行。这种特性让我们可以做一些优化,比如避免不必要的操作。
示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
 
// 中间操作:过滤和映射
Stream<Integer> stream = numbers.stream()
                                .filter(num -> num > 2)  // 过滤出大于 2 的数字
                                .map(num -> num * 2);     // 每个数字乘以 2
 
// 终端操作:打印结果
stream.forEach(System.out::println);  // 输出 6, 8, 10

在上面的代码中,filter() 和 map() 是中间操作,只有在调用 forEach()(终端操作)时,才会实际进行数据处理。

6. 并行流(Parallel Stream)

Stream 还支持并行流(parallelStream()),它可以利用多核 CPU 的优势来加速处理。当你需要处理大量数据时,使用并行流可以显著提高效率。
示例:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
 
// 使用 parallelStream() 进行并行处理
numbers.parallelStream()
       .forEach(num -> System.out.println(num + " processed by " + Thread.currentThread().getName()));

总结

  • Stream 让你以声明式的方式处理数据,代码更加简洁和易读。
  • 中间操作(如 filter、map)是对流的转换,终端操作(如 collect、forEach)才会触发数据的实际处理。
  • 惰性求值:Stream 的中间操作不会立即执行,而是直到终端操作调用时才会进行计算。
  • 并行流:Stream 支持并行处理,可以通过 parallelStream() 提升处理大量数据的效率。

二、具体用法

1.List、Set 元素转化为逗号分隔的字符串的几种方式

实际开发过程中我们经常会将List、Set的元素转化为逗号分隔的字符串,但是你知道有哪些常见的方式呢?
常见的方式
方式一:【推荐】

String.join(",", list);

方式二:

list.stream().collect(Collectors.joining(","));

方式三:guava的Joiner

Joiner.on(",").join(list);

Demo

package com.it;

import com.google.common.base.Joiner;

import java.util.ArrayList;
import java.util.stream.Collectors;

public class JoinTest {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

        // 方式一
        String str1 = String.join(",", list);

        // 方式二
        String str2 = list.stream().collect(Collectors.joining(","));

        // 方式三 guava的Joiner
        String str3 = Joiner.on(",").join(list);
    }
}

参考

2.类型转换

  1. integer 转 long类型
    // 将每个Integer元素转换为Long类型:
List<Long> collect = List.stream().map(Integer::longValue).collect(Collectors.toList());
  1. string数组转换成list类型
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
 
public class StringArrayToListOfLongWithStream {
    public static void main(String[] args) {
        // 示例字符串数组
        String[] stringArray = {"1", "2", "3", "4", "5"};
        
        // 使用Stream API将字符串数组转换为List<Long>
        List<Long> longList = Arrays.stream(stringArray)
                                    .map(Long::valueOf) // 将字符串转换为Long
                                    .collect(Collectors.toList()); // 收集到List中
        
        // 打印结果,验证转换是否成功
        System.out.println(longList);
    }
}
  1. string用逗号拆分,如何转成list数组
    在Java中,如果你有一个以逗号分隔的字符串,并希望将其转换为一个List,你可以使用以下几种方法来实现这一需求。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
 
public class StringToListLong {
    public static void main(String[] args) {
        String input = "1,2,3,4,5";
        List<Long> longList = Arrays.stream(input.split(","))
                                    .map(Long::parseLong)
                                    .collect(Collectors.toList());
        System.out.println(longList);
    }
}

总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值