Java第十三篇:Stream流

目录

前言

引入:

一、Stream流与传统方法的对比

二、创建流

1.List创建:

2.Map创建:

3.数组创建:

[4. 通过生成器创建:](#4. 通过生成器创建:)

[5. 从文件创建:](#5. 从文件创建:)

三、操作流

[1. filter() - 过滤操作](#1. filter() - 过滤操作)

[2. map() - 映射转换](#2. map() - 映射转换)

[3. sorted() - 默认排序](#3. sorted() - 默认排序)

[4. sorted() - 自定义排序](#4. sorted() - 自定义排序)

[5. distinct() - 去重操作](#5. distinct() - 去重操作)

[6. limit() - 截取前N个元素](#6. limit() - 截取前N个元素)

[7. skip() - 跳过前N个元素](#7. skip() - 跳过前N个元素)

[8. forEach() - 遍历操作](#8. forEach() - 遍历操作)

[9. collect() - 收集结果](#9. collect() - 收集结果)

[10. anyMatch() - 任意匹配](#10. anyMatch() - 任意匹配)

[11. allMatch() - 全部匹配](#11. allMatch() - 全部匹配)

[12. noneMatch() - 无匹配](#12. noneMatch() - 无匹配)

[13. findFirst() - 获取第一个元素](#13. findFirst() - 获取第一个元素)

[14. findAny() - 获取任意元素](#14. findAny() - 获取任意元素)

[15. reduce() - 归约操作](#15. reduce() - 归约操作)

[16. parallelStream() - 并行流](#16. parallelStream() - 并行流)

四、终结流

1.foreach终结

2.count终结

3.max终结

4.Collect收集(!!!)

总结


前言

今天我们来学习Stream流的相关知识。


引入:

今天早上,乐锅用纸叠了一艘小船。当我在陆地上推着它走时,每一步都显得笨拙而缓慢------需要弯腰、用力、再弯腰、再用力。但当我把它轻轻放入溪流中,神奇的事情发生了:小船顺着水流自然滑行,轻盈、流畅,速度远超在陆地上的费力推动。这就是------Stream流

有了Stream流,我们不再关注如何遍历集合 ,而是专注于数据转换的意图 。就像溪流不会关心小船的形状,它只负责将小船从源头带到大海。Stream流接管了底层的迭代逻辑,让我们的代码变得:更简洁、更易读、更高效。


一、Stream流与传统方法的对比

复制代码
  public static void main(String[] args) {
        //创建一个集合
        Collection<String> data=new ArrayList<>();

        data.add("张强");
        data.add("赵敏");
        data.add("周芷若");
        data.add("张傻傻");
        data.add("张翠花");
        data.add("何东");
}

要求:遍历输出姓张且名字长度为3的集合

复制代码
      1.传统方法,for加if
        List<String> newdata=new ArrayList<>();
       for(String datas:data){
           if(datas.startsWith("张")&&datas.length()==3){
               newdata.add(datas);
           }
        }
        System.out.println(newdata);

//       2.stream方法
        List<String> newdatas=data.stream().//转换成Stream流
                                   filter(d->d.startsWith("张")).//调用filter api来进行排除
                                   filter(datas->datas.length()==3).
                                   collect(Collectors.toList());//收集成集合
        System.out.println(newdatas);

我们可以看到代码换行并翻译以后可读性大大增加

这也是流的初心:方便数据处理与代码玛阅读


二、创建流

1.List创建:

复制代码
        Collection<String> list=new ArrayList<>();
        Stream<String> s1=list.stream();

2.Map创建:

复制代码
         //map
        Map<String,Integer> s2=new HashMap<>();
        //获取map键的流
        Stream<String> s3=s2.keySet().stream();

        //获取map值的流
        Stream<Integer> s4=s2.values().stream();

        //获取map值和键的流
        Stream<Map.Entry<String,Integer>>s5=s2.entrySet().stream();

3.数组创建:

复制代码
     //获取数组的流
        String[] name={"小明","小周","小李","小王"};
//        将数组 name 转换为 Stream 流
        Stream<String> s6= Arrays.stream(name);
        System.out.println(s6.count());

        //直接创建流
        Stream<String> s7=Stream.of(name);
        Stream<String> s8=Stream.of("小明","小周","小李","小王");

4. 通过生成器创建:

复制代码
// 4.1 无限流:generate()
//生成随机数无限流
Stream<Double> randomStream = Stream.generate(Math::random);
//生成常量值无限流
Stream<String> constantStream = Stream.generate(() -> "constant");

// 4.2 无限流:iterate()
// 0, 1, 2, 3, 4...
Stream<Long> fibonacciStream = Stream.iterate(0L, n -> n + 1); //这里的L是long类型意思
// 1, 2, 4, 8, 16...
Stream<Long> customIterate = Stream.iterate(1L, n -> n * 2); 

// 注意:无限流需要配合limit()使用,否则会无限执行
List<Long> first10Numbers = Stream.iterate(0L, n -> n + 1)
                                 .limit(10)
                                 .collect(Collectors.toList());

5. 从文件创建:

复制代码
 public static void main(String[] args) {
        try {
            // 读取文件的每一行作为流
            Stream<String> linesStream = Files.lines(Paths.get("data.txt"));
            
            // 处理文件内容
            linesStream.forEach(System.out::println);
            
            // 注意:文件流需要关闭
            linesStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

三、操作流

1. filter() - 过滤操作

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)  // 过滤出偶数
    .collect(Collectors.toList());
// 结果: [2, 4, 6, 8, 10]

2. map() - 映射转换

复制代码
List<String> words = Arrays.asList("java", "python", "c++", "javascript");
List<String> upperCaseWords = words.stream()
    .map(String::toUpperCase)  // 将每个字符串转换为大写
    .collect(Collectors.toList());
// 结果: ["JAVA", "PYTHON", "C++", "JAVASCRIPT"]

3. sorted() - 默认排序

复制代码
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9, 3);
List<Integer> sortedNumbers = numbers.stream()
    .sorted()  // 使用自然排序
    .collect(Collectors.toList());
// 结果: [1, 2, 3, 5, 8, 9]

4. sorted() - 自定义排序

复制代码
List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
List<String> sortedByLength = words.stream()
    .sorted(Comparator.comparingInt(String::length))  // 按字符串长度排序
    .collect(Collectors.toList());
// 结果: ["date", "apple", "cherry", "banana"]

5. distinct() - 去重操作

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4, 4, 4, 4);
List<Integer> uniqueNumbers = numbers.stream()
    .distinct()  // 去除重复元素
    .collect(Collectors.toList());
// 结果: [1, 2, 3, 4]

6. limit() - 截取前N个元素

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> firstThree = numbers.stream()
    .limit(3)  // 只取前3个元素
    .collect(Collectors.toList());
// 结果: [1, 2, 3]

7. skip() - 跳过前N个元素

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> skipFirstThree = numbers.stream()
    .skip(3)  // 跳过前3个元素
    .collect(Collectors.toList());
// 结果: [4, 5, 6, 7, 8, 9, 10]

8. forEach() - 遍历操作

复制代码
List<String> words = Arrays.asList("hello", "world", "java", "stream");
words.stream()
    .forEach(System.out::println);  // 对每个元素执行操作
// 输出:
// hello
// world
// java
// stream

9. collect() - 收集结果

复制代码
List<String> words = Arrays.asList("java", "python", "c++", "javascript");

// 收集到List
List<String> resultList = words.stream()
    .filter(w -> w.length() > 3)
    .collect(Collectors.toList());

// 收集到Set
Set<String> resultSet = words.stream()
    .collect(Collectors.toSet());

// 收集到Map
Map<String, Integer> wordLengthMap = words.stream()
    .collect(Collectors.toMap(
        Function.identity(), 
        String::length
    ));
// 结果: {java=4, python=6, c++=3, javascript=10}

10. anyMatch() - 任意匹配

复制代码
List<String> words = Arrays.asList("java", "python", "c++", "javascript");
boolean hasLongWord = words.stream()
    .anyMatch(w -> w.length() > 10);  // 是否存在长度大于10的单词
// 结果: true (因为"javascript"长度为10,不大于10,所以是false)
// 修正:javascript长度是10,不大于10,所以结果是false

11. allMatch() - 全部匹配

复制代码
List<Integer> numbers = Arrays.asList(2, 4, 6, 8, 10);
boolean allEven = numbers.stream()
    .allMatch(n -> n % 2 == 0);  // 是否所有数字都是偶数
// 结果: true

12. noneMatch() - 无匹配

复制代码
List<String> words = Arrays.asList("java", "python", "c++", "javascript");
boolean noEmptyStrings = words.stream()
    .noneMatch(String::isEmpty);  // 是否没有空字符串
// 结果: true

13. findFirst() - 获取第一个元素

复制代码
List<String> words = Arrays.asList("java", "python", "c++", "javascript");
Optional<String> firstWord = words.stream()
    .filter(w -> w.startsWith("j"))
    .findFirst();  // 获取第一个以"j"开头的单词
// 结果: Optional["java"]

14. findAny() - 获取任意元素

复制代码
List<String> words = Arrays.asList("java", "python", "c++", "javascript");
Optional<String> anyWord = words.stream()
    .filter(w -> w.length() > 5)
    .findAny();  // 获取任意一个长度大于5的单词
// 结果: 可能是"python"或"javascript"

15. reduce() - 归约操作

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream()
    .reduce((a, b) -> a + b);  // 求和归约
// 结果: Optional[15]

// 带初始值的reduce
int product = numbers.stream()
    .reduce(1, (a, b) -> a * b);  // 求乘积,初始值为1
// 结果: 120

16. parallelStream() - 并行流

复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = numbers.parallelStream()  // 使用并行流
    .map(n -> {
        System.out.println("Processing " + n + " on thread: " + Thread.currentThread().getName());
        return n * 2;
    })
    .reduce(0, Integer::sum);
// 结果: 110 (2+4+6+8+10+12+14+16+18+20)
// 输出会显示在不同线程上处理

四、终结流

复制代码
//先创建集合
public static void main(String[] args) {
        List<Teacher> teachers=new ArrayList<>();
        teachers.add(new Teacher("小明",8000.0,18));
        teachers.add(new Teacher("小红", 9500.0, 25));
        teachers.add(new Teacher("小刚", 7500.0, 22));
        teachers.add(new Teacher("小丽", 10000.0, 28));
        teachers.add(new Teacher("小强", 8500.0, 30));

1.foreach终结

复制代码
    //foreach终结
    teachers.stream().
             filter(teacher ->teacher.getAge()>25).
             forEach(System.out::println);

2.count终结

复制代码
 long count=teachers.stream().
                    filter(teacher -> teacher.getPrice()>8000).count();

        System.out.println(count);

3.max终结

复制代码
  Optional<Teacher> max=teachers.stream().
        max(Comparator.comparingDouble(Teacher::getPrice));
        Teacher teacher=max.get();
        System.out.println(teacher);

4.Collect收集(!!!)

复制代码
       List<String> list=new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.add("张三丰");
        list.add("张翠山");

        Stream<String>s1=list.stream().filter(s->s.startsWith("张"));
        //收集到list集合
        List<String> list1=s1.collect(Collectors.toList());
        System.out.println(list1);

        //收集到set集合
        Stream<String> s2=list.stream().filter(s->s.startsWith("张"));
        Set<String> list2=s2.collect(Collectors.toSet());
        System.out.println(list2);

        //收集到数组
        Stream<String> s3=list.stream().filter(s -> s.startsWith("张"));
        Object[] array=s3.toArray();
        System.out.println(Arrays.toString(array));

        //收集到map集合
        Map<String,Integer> map = teachers.stream().collect(Collectors.toMap(Teacher::getName,Teacher::getAge));
        System.out.println(map);

总结

今天的Stream流就到这里结束了。

在这特别感谢牛肉哥关于Stream流api的详细总结,以及平时对我博客的指导和鼓励。

https://liyuanxin.blog.csdn.net/article/details/131773918?fromshare=blogdetail&sharetype=blogdetail&sharerId=131773918&sharerefer=PC&sharesource=2502_94242477&sharefrom=from_linkhttps://liyuanxin.blog.csdn.net/article/details/131773918?fromshare=blogdetail&sharetype=blogdetail&sharerId=131773918&sharerefer=PC&sharesource=2502_94242477&sharefrom=from_link我是新手程序猿乐锅。本次分享到此结束,感谢大家的观看与支持!如果本期内容对您有帮助,欢迎**点赞、收藏,**您的支持将是我持续创作的最大动力,谢谢!

相关推荐
林三的日常2 小时前
SpringBoot + Druid SQL Parser 解析表名、字段名(纯Java,最佳方案)
java·spring boot·sql
殷忆枫2 小时前
AI学习笔记三十六:基于 YOLOv8 与 Qwen3.5 的多模态视频行为分析系统
笔记·学习·yolo
小陈phd2 小时前
多模态大模型学习笔记(三十七)——模型管理平台实战:Ollama本地部署与全流程指南
笔记·学习
deviant-ART2 小时前
java stream 的 findFirst 和 findAny 踩坑点
java·开发语言·后端
青衫码上行2 小时前
【从零开始学习JVM】字符串常量池
java·jvm·学习·面试·string
handler012 小时前
Linux 基本指令知识点(1)
linux·c++·笔记
历程里程碑2 小时前
55 Linux epoll高效IO实战指南
java·linux·服务器·开发语言·前端·javascript·c++
sheeta19982 小时前
苍穹外卖Day09Day10笔记
笔记
何包蛋H2 小时前
Java并发编程核心:JUC、AQS、CAS 完全指南
java·开发语言