Java Stream流(详解)

Java Stream流(详解)一 Stream 流引入 Lambda 表达式 基于 Lambda 所带来的函数式编程 又引入了一个全新的 Stream 概念 用于解决集合类库既有的鼻端 Lambda 表达式详解在上篇博客内容 现有一个需求 将 list 集合中姓张的元素过滤到一个新的集合中然后将过滤出来的姓张的元素中 再过滤出来长度为 3 的元素 存储到一个新的集合中 1 用常规方法解决需求

一、Stream流引入

        Lambda表达式,基于Lambda所带来的函数式编程,又引入了一个全新的Stream概念,用于解决集合类库既有的鼻端。(Lambda表达式详解在上篇博客内容)

        现有一个需求:

                将list集合中姓张的元素过滤到一个新的集合中

                然后将过滤出来的姓张的元素中,再过滤出来长度为3的元素,存储到一个新的集合中

                1.用常规方法解决需求

 // 已知的知识来解决需求 List 
  
    list1 = new ArrayList<>(); list1.add("张老三"); list1.add("张小三"); list1.add("李四"); list1.add("赵五"); list1.add("张六"); list1.add("王八"); ArrayList 
   
     list2 = new ArrayList<>(); // 1.将list集合中姓张的元素过滤到一个新的集合中 for(String name : list1){ if(name.startsWith("张")){ list2.add(name); } } ArrayList list3 = new ArrayList(); for (String name : list2) { if (name.length() == 3){ list3.add(name); } } System.out.println(list3); 输出结果: [张老三, 张小三] 
    
  

              2.用Stream流操作集合,获取流,过滤操作,打印输出

list1.stream().filter((String name)->name.startsWith("张")).filter((String name)->name.length()==3).forEach((String name)->{ System.out.println("符合条件的姓名:" + name); });

                ( 看不懂没关系,下面会讲到该方法,这里只是用来引入的)

二、Stream流的格式

Stream 
  
    filter(Predicate 
    predicate); -----> 参数:public interface Predicate 
   
     (函数式接口) ----> 抽象方法:boolean test(T t); -----> 参数:public interface Consumer 
    
      (函数式接口) ----> 抽象方法:boolean test(T t); 
     
    
  

     整体代码看来:流式思想 类似于 工厂车间的“流水线”

                ( 看不懂没关系,下面会讲到该方法,这里只是用来引入的)

三、获取流

        根据集合来获取:

                根据Collection获取流:

                        Collection接口中有一个stream()方法,可以获取流

 default Stream 
  
    stream() 
  

                1.根据List获取流

                2.根据Set获取流

                3.根据Map获取流

                        3.1根据Map集合的键来获取流

                        3.2根据Map集合的值获取流

                        3.3根据Map集合的键值对对象获取流

                4.根据数组获取流

        代码演示:

                1.根据List集合获取流

 // 创建List集合 List 
  
    list = new ArrayList<>(); list.add("张老三"); list.add("张小三"); list.add("李四"); list.add("赵五"); list.add("张六"); list.add("王八"); Stream 
   
     stream1 = list.stream(); 
    
  

                2.根据Set集合获取流

 // 创建List集合 Set 
  
    set = new HashSet<>(); list.add("张老三"); list.add("张小三"); list.add("李四"); list.add("赵五"); list.add("张六"); list.add("王八"); Stream 
   
     stream2 = set.stream(); 
    
  

                3.根据Map集合获取流

 // 创建Map集合 Map 
  
    map = new HashMap<>(); map.put(1,"张老三"); map.put(2,"张小三"); map.put(3,"李四"); map.put(4,"赵五"); map.put(5,"张六"); map.put(6,"王八"); // 3.1根据Map集合的键获取流 Set 
   
     map1 = map.keySet(); Stream 
    
      stream3 = map1.stream(); // 3.2根据Map集合的值获取流 Collection 
     
       map2 = map.values(); Stream 
      
        stream4 = map2.stream(); // 3.3根据Map集合的键值对对象获取瑞 Set 
       
         > map3 = map.entrySet(); Stream 
        
          > stream5 = map3.stream(); 
         
        
       
      
     
    
  

                4.根据数组获取流

 // 根据数组获取流 String[] arr = {"张颜宇","张三","李四","赵五","刘六","王七"}; Stream 
  
    stream6 = Stream.of(arr); 
  

        

四、Stream流的常用方法

        Stream流的常用方法:

                终结方法:返回值类型不再是Stream接口本身类型的方法,例如:forEach方法和count方法

                非终结方法/延迟方法:返回值类型仍然是Stream接口自身类型的方法,除了终结方法都是延迟方法。例如:filter,limit,skip,map,conat

方法名称 方法作用 方法种类 是否支持链式调用
count 统计个数 终结方法
forEach 逐一处理 终结方法
filter 过滤 函数拼接
limit 取用前几个 函数拼接
skip 跳过前几个 函数拼接
map 映射 函数拼接
concat 组合 函数拼接

        方法演示:

                1.count方法:

                        long count (); 统计流中的元素,返回long类型数据

 List 
  
    list = new ArrayList<>(); list.add("张老三"); list.add("张小三"); list.add("李四"); list.add("赵五"); list.add("张六"); list.add("王八"); long count = list.stream().count(); System.out.println("集合中的元素个数是:" + count); 输出结果: 集合中的元素个数是:6 
  

                2.filter方法:

                        Stream

filter(Predicate
predicate); 过滤出满足条件的元素

                                参数Predicate:函数式接口,抽象方法:boolean test (T  t)

                                Predicate接口:是一个判断接口

 // 获取stream流 Stream 
  
    stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七"); // 需求:过去出姓张的元素 stream.filter((String name)->{ return name.startsWith("张"); }).forEach((String name)->{ System.out.println("流中的元素" + name); }); 
  

                        (上面引入Stream流时,就用到了这个方法)

                3.forEach方法

                        注意:

                                1.此方法并不保证元素的逐一消费动作在流中是有序进行的(元素可能丢失)

                                2.Consumer是一个消费接口(可以获取流中的元素进行遍历操作,输出出去),可以使用Lambda表达式

 List 
  
    list = new ArrayList<>(); list.add("张老三"); list.add("张小三"); list.add("李四"); list.add("赵五"); list.add("张六"); list.add("王八"); // 函数模型:获取流 --> 注意消费流中的元素 list.stream().forEach((String name)->{ System.out.println(name); }); 输出结果: 张老三 张小三 李四 赵五 张六 王八 
  

                4.limit方法

                        Stream

limit(long maxSize);   取用前几个元素

                        注意:

                                参数是一个long 类型,如果流的长度大于参数,则进行截取;否则不进行操作

 // 获取流的长度 Stream 
  
    stream1 = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七"); // 需求:保留前三个元素 stream1.limit(3).forEach((String name)->{ System.out.println("流中的前三个元素是:" + name); }); 输出结果: 流中的前三个元素是:张老三 流中的前三个元素是:张小三 流中的前三个元素是:李四 
  

                5.map方法

                        

Stream

map(Function
mapper;

                            参数Function

:函数式接口,抽象方法:R apply(T t);

                                Function

:其实就是一个类型转换接口(T和R的类型可以一致,也可以不一致)





 // 获取Stream流 Stream 
  
    stream1 = Stream.of("11","22","33","44","55"); // 需求:把stream1流中的元素转换为int类型 stream1.map((String s)->{ return Integer.parseInt(s); // 将String类型的s进行转换为Integer类型的元素,并返回 }).forEach((Integer i)->{ System.out.println(i); // 将转换后的int类型的元素逐一输出 }); 输出结果: 11 22 33 44 55 
  

                6.skip方法

                    Stream

skip(long n);     跳过前几个元素

                    注意:
                        如果流的当前长度大于n,则跳过前n个,否则将会得到一个长度为0的空流


 // 获取stream流 Stream 
  
    stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七"); stream.skip(3).forEach((String name)->{ System.out.println("跳过前三个,打印剩下的" + name); }); 输出结果: 跳过前三个,打印剩下的赵五 跳过前三个,打印剩下的刘六 跳过前三个,打印剩下的王七 
  

                7.concat方法

    public static

Stream

concat(Stream
a, Stream
b)

            –> 合并两个流


 Stream 
  
    stream1 = Stream.of("11","22","33","44","55"); Stream 
   
     stream2 = Stream.of("张颜宇", "张三", "李四", "赵五", "刘六", "王七"); // 需求:合并两个流 Stream 
    
      stream = Stream.concat(stream1,stream2); stream.forEach((String name)->{ System.out.print(name); }); 输出结果: 张颜宇张三李四赵五刘六王七 
     
    
  

五、收集Stream流

        Stream流中提供了一个方法,可以把流中的数据收集到单例集合中

                

R collect(Collector
collector);     把流中的数据手机到单列集合中

                    返回值类型是R。R指定为什么类型,就是手机到什么类型的集合
                    参数Collector
中的R类型,决定把流中的元素收集到哪个集合中
                    参数Collector如何得到 ?,可以使用 java.util.stream.Collectors工具类中的静态方法:
                        – public static

Collector

> toList():转换为List集合

                        – public static

Collector

> toSet() :转换为Set集合









 List 
  
    list2 = new ArrayList<>(); list2.add("张老三"); list2.add("张小三"); list2.add("李四"); list2.add("赵五"); list2.add("张六"); list2.add("王八"); // 需求:过滤出姓张的并且长度为3的元素 Stream 
   
     stream = list2.stream().filter((String name) -> { return name.startsWith("张"); }).filter((String name) -> { return name.length() == 3; }); // stream 收集到单列集合中 List 
    
      list = stream.collect(Collectors.toList()); System.out.println(list); // stream 手机到单列集合中 Set 
     
       set = stream.collect(Collectors.toSet()); System.out.println(set); 
      
     
    
  

                        

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/212543.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午7:49
下一篇 2026年3月18日 下午7:49


相关推荐

  • redis过期删除机制(redis过期策略和删除策略)

    在Redis中,内存的大小是有限的,所以为了防止内存饱和,需要实现某种键淘汰策略。主要有两种方法,一种是当Redis内存不足时所采用的内存释放策略。另一种是对过期键进行删除的策略,也可以在某种程度上释放内存。1、内存释放的策略Redis中有专门释放内存的函数:freeMmoryIfNeeded。每当执行一个命令的时候,就会调用该函数来检测内存是否够用。如果已用内存大于最大内存限制,它就会进行内存释…

    2022年4月17日
    75
  • 进程调度有可抢占 哪种开销更大_什么时候用多线程什么时候用多进程

    进程调度有可抢占 哪种开销更大_什么时候用多线程什么时候用多进程线程调度为什么比进程调度更少开销?在对比进程调度与线程调度的开销前,我们需要明白两点:进程与线程的差异任务调度的开销进程与线程的差异我们首先要明白,线程和进程有什么关系?从概念上来讲,线程是进程的一部分,只是任务调度相关的部分,所以我们才说,“线程是调度的最小单位”。进程拥有着资源,这些资源不属于某一个特定线程,因为所有线程共享进程拥有的资源,所以我们才说,“进程是资源分配的最小单位…

    2025年11月11日
    4
  • 多模型融合权重如何训练_单因子模型

    多模型融合权重如何训练_单因子模型本篇文章有别于传统的多因子研究,我们并未将重点放在阿尔法因子的挖掘上,而是通过对股票组合的权重优化计算,找到了在市值中性、行业中性、风格因子中性约束下的最优投资组合,以及验证得到的组合权重是否满足了约束条件。结构化多因子风险模型首先对收益率进行简单的线性分解,分解方程中包含四个组成部分:股票收益率、因子暴露、因子收益率和特质因子收益率。那么,第只股票的线性分解如下所示:rj=x1f1+x2f2+x3f3+x4f4⋅⋅⋅⋅xKfK+ujr_j=x_1f_1+x_2f_2+x_3f_3+x_4f_4···

    2022年10月6日
    4
  • 100个常用的deepseek指令(收藏)

    100个常用的deepseek指令(收藏)

    2026年3月16日
    4
  • html简单登录页面代码「建议收藏」

    html简单登录页面代码「建议收藏」图片必须是在Imges下的否则显示不出来(复制代码的话把图片换成你的图片就好了)代码如下&lt;html&gt;&lt;head&gt;&lt;title&gt;tes

    2022年6月13日
    36
  • react脚手架有哪些_vue脚手架3搭建项目

    react脚手架有哪些_vue脚手架3搭建项目前言如何快速搭建一个httprunner项目呢?我们可以使用脚手架,脚手架就是自动地创建一些目录,形成一个项目的架构,不需要我们再手动的去创建查看创建新项目的命令先来查看一下帮助命令httpr

    2022年8月6日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号