Stream流详解

当我们对一个集合中的元素进行多次过滤应该怎样做?

下面看一个案例

  • 按照下面的要求完成集合的创建和遍历

    • 创建一个集合,存储多个字符串元素

    • 把集合中所有以"张"开头的元素存储到一个新的集合

    • 把"张"开头的集合中的长度为3的元素存储到一个新的集合

    • 遍历上一步得到的集合

  • 原始方式示例代码

public class MyStream1 {public static void main(String[] args) {//集合的批量添加ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));//list.add()//遍历list1把以张开头的元素添加到list2中。ArrayList<String> list2 = new ArrayList<>();for (String s : list1) {if(s.startsWith("张")){list2.add(s);}}//遍历list2集合,把其中长度为3的元素,再添加到list3中。ArrayList<String> list3 = new ArrayList<>();for (String s : list2) {if(s.length() == 3){list3.add(s);}}for (String s : list3) {System.out.println(s);}      }
}
  • 使用Stream流示例代码

public class test1 {public static void main(String[] args) {//集合的批量添加ArrayList<String> list1 = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));//Stream流list1.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));}
}

由此可见

Java Stream流的好处体现在以下几个方面:

  1. 简化代码:Stream API允许开发者通过声明性方式处理数据,这意味着可以通过更少的代码实现相同的功能,从而提高代码的简洁性和可读性。
  2. 提高可维护性:由于Stream流的代码更加简洁,因此也更容易维护。当业务逻辑复杂时,使用Stream可以减少出错的机会,并且使得代码更加清晰。
  3. 函数式编程:Stream流基于函数式编程的思想,这使得它能够很好地支持抽象思维和函数式操作,有助于解决复杂的业务逻辑问题。
  4. 性能优化:Stream API设计时就考虑到了性能因素,它在内部进行了优化,比如延迟执行和短路操作等,可以在不修改代码的情况下享受性能提升的好处。
  5. 避免显式数据存储:Stream流不是一种数据结构,它不需要显式地存储数据,而是对数据进行加工和处理,这有助于减少内存的使用。
  6. 流水线操作:Stream流的处理方式类似于工厂的生产线,每个操作都是流水线上的一个工序,这样的设计使得数据处理流程更加清晰和高效。
  7. 避免手动管理线程:在使用Stream进行并行处理时,开发者不需要手动管理线程,Stream API会负责这部分工作,这样可以更加专注于业务逻辑本身。
  8. 易于并行化:Stream流可以很容易地将顺序流转换为并行流,从而利用多核处理器的优势,提高数据处理的速度。
  9. 强大的操作:Stream API提供了丰富的操作,如过滤、映射、排序等,这些操作可以组合起来形成强大的数据处理链。
  10. 灵活的数据源:Stream流不仅可以从集合创建,还可以从数组、I/O通道等多种数据源创建,这为数据处理提供了极大的灵活性。

总的来说,Java Stream流通过提供一种高效、简洁、易于维护的方式来处理数据,极大地提升了开发效率和程序的性能。

Stream流的三类方法

  • 获取Stream流

    • 创建一条流水线,并把数据放到流水线上准备进行操作

  • 中间方法

    • 流水线上的操作

    • 一次操作完毕之后,还可以继续进行其他操作

  • 终结方法

    • 一个Stream流只能有一个终结方法

    • 是流水线上的最后一个操作

    • 生成Stream流的方式

      • Collection体系集合

        使用默认方法stream()生成流, default Stream<E> stream()

      • public class test5 {public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};//获取stream流Arrays.stream(arr).forEach(s -> System.out.println(s));}
        }
      • Map体系集合

        把Map转成Set集合,间接的生成流

      • public class test3 {public static void main(String[] args) {//双列集合//1.创建双列集合HashMap<String,Integer> hm = new HashMap<>();//添加数据hm.put("aaa",111);hm.put("bbb",111);hm.put("ccc",111);hm.put("ddd",111);//3.第一种获取Stream流hm.keySet().stream().forEach(s -> System.out.println(s));//3.第二种获取Stream流hm.entrySet().stream().forEach(s -> System.out.println(s));}
        }

      • 数组

        通过Arrays中的静态方法stream生成流

      • public class test2 {public static void main(String[] args) {//单列集合获取Stream流ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"a","b","c","d");list.stream().forEach(s -> System.out.println(s));}
        }
      • 同种数据类型的多个数据

        通过Stream接口的静态方法of(T... values)生成流

      • public class test4 {public static void main(String[] args) {Stream.of(1,2,3,4,5).forEach(s -> System.out.println(s));}
        }

Stream流中间操作方法

  • 概念

中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作

  • 常见方法

方法名说明
Stream<T> filter(Predicate predicate)用于对流中的数据进行过滤
Stream<T> limit(long maxSize)返回此流中的元素组成的流,截取前指定参数个数的数据
Stream<T> skip(long n)跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static <T> Stream<T> concat(Stream a, Stream b)合并a和b两个流为一个流
Stream<T> distinct()返回由该流的不同元素(根据Object.equals(Object) )组成的流
public class MyStream3 {public static void main(String[] args) {
//        Stream<T> filter(Predicate predicate):过滤
//        Predicate接口中的方法	boolean test(T t):对给定的参数进行判断,返回一个布尔值ArrayList<String> list = new ArrayList<>();list.add("张三丰");list.add("张无忌");list.add("张翠山");list.add("王二麻子");list.add("张良");list.add("谢广坤");//filter方法获取流中的 每一个数据.//而test方法中的s,就依次表示流中的每一个数据.//我们只要在test方法中对s进行判断就可以了.//如果判断的结果为true,则当前的数据留下//如果判断的结果为false,则当前数据就不要.
//        list.stream().filter(
//                new Predicate<String>() {
//                    @Override
//                    public boolean test(String s) {
//                        boolean result = s.startsWith("张");
//                        return result;
//                    }
//                }
//        ).forEach(s-> System.out.println(s));//因为Predicate接口中只有一个抽象方法test//所以我们可以使用lambda表达式来简化
//        list.stream().filter(
//                (String s)->{
//                    boolean result = s.startsWith("张");
//                        return result;
//                }
//        ).forEach(s-> System.out.println(s));list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s));}
}

limit&skip代码演示

public class StreamDemo02 {public static void main(String[] args) {//创建一个集合,存储多个字符串元素ArrayList<String> list = new ArrayList<String>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");//需求1:取前3个数据在控制台输出list.stream().limit(3).forEach(s-> System.out.println(s));System.out.println("--------");//需求2:跳过3个元素,把剩下的元素在控制台输出list.stream().skip(3).forEach(s-> System.out.println(s));System.out.println("--------");//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出list.stream().skip(2).limit(2).forEach(s-> System.out.println(s));}
}

concat&distinct代码演示

public class StreamDemo03 {public static void main(String[] args) {//创建一个集合,存储多个字符串元素ArrayList<String> list = new ArrayList<String>();list.add("林青霞");list.add("张曼玉");list.add("王祖贤");list.add("柳岩");list.add("张敏");list.add("张无忌");//需求1:取前4个数据组成一个流Stream<String> s1 = list.stream().limit(4);//需求2:跳过2个数据组成一个流Stream<String> s2 = list.stream().skip(2);//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
//        Stream.concat(s1,s2).forEach(s-> System.out.println(s));//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s));}
}
public class test6 {public static void main(String[] args) {/*map 转换流中的数据类型注意点1: 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程注意点2: 修改Stream流中的数据,不会影响原来集合或者数组中的数据*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"张三-15","李四-16");//需求: 只获取里面的年龄并进行打印//String -> int//第一个类型: 流中原来的数据类型//第二个类型: 要转成之后的数据list.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {String[] arr = s.split("-");String ageString = arr[1];int age = Integer.parseInt(ageString);return age;}}).forEach(s -> System.out.println(s));list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> System.out.println(s));}
}

Stream流终结操作方法

  • 概念

    终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作

  • 常见方法

    方法名说明
    void forEach(Consumer action)对此流的每个元素执行操作
    long count()返回此流中的元素数

Stream流的收集操作

  • 概念

    对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中

  • 常用方法

    方法名说明
    R collect(Collector collector)把结果收集到集合中
  • 工具类Collectors提供了具体的收集方式

方法名说明
public static <T> Collector toList()把元素收集到List集合中
public static <T> Collector toSet()把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper)把元素收集到Map集合中
public class StreamTest5 {// toList和toSet方法演示public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();for (int i = 1; i <= 10; i++) {list1.add(i);}list1.add(10);list1.add(10);list1.add(10);list1.add(10);list1.add(10);//filter负责过滤数据的.//collect负责收集数据.//获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.//Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.List<Integer> list = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());System.out.println(list);Set<Integer> set = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toSet());System.out.println(set);}
}
public class StreamTest6 {public static void main(String[] args) {/*Stream流的收集方法 toMap方法演示创建一个ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年龄"zhangsan,23""lisi,24""wangwu,25"保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值*/ArrayList<String> list = new ArrayList<>();list.add("zhangsan,23");list.add("lisi,24");list.add("wangwu,25");Map<String, Integer> map = list.stream().filter(s -> {String[] split = s.split(",");int age = Integer.parseInt(split[1]);return age >= 24;}//   collect方法只能获取到流中剩余的每一个数据.//在底层不能创建容器,也不能把数据添加到容器当中).collect(Collectors.toMap(s -> s.split(",")[0],s -> Integer.parseInt(s.split(",")[1])));System.out.println(map);}}

案例来源:

//https://www.bilibili.com/video/BV17F411T7Ao/?spm_id_from=333.337.search-card.all.click

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/709788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

金三银四,自动化测试面试题精选【美团二面】

面试一般分为技术面和hr面&#xff0c;形式的话很少有群面&#xff0c;少部分企业可能会有一个交叉面&#xff0c;不过总的来说&#xff0c;技术面基本就是考察你的专业技术水平的&#xff0c;hr面的话主要是看这个人的综合素质以及家庭情况符不符合公司要求&#xff0c;一般来…

Redis 消息队列:构建消息代理的 4 个简单步骤

消息代理是一种使系统、应用程序和服务能够通信和交换信息的软件。它在正式消息传递协议之间转换消息,并允许相互依赖的服务直接“对话”,即使是用不同语言编写或在不同平台上实现也是如此。在微服务中使用异步通信时,通常会使用消息代理。 消息代理可确保可靠且稳定的通信,…

golang 泛型详解

目录 概念 ~int vs .int 常见的用途和错误 结论&#xff1a; 概念 Go 在1.18 中添加了泛型&#xff0c;这样Go 就可以在定义时不定义类型&#xff0c;而是在使用时进行类型的定义&#xff0c;并且还可以在编译期间对参数类型进行校验。Go 目前只支持泛型方法&#xff0c;还…

Machine Vision Technology:Lecture2 Linear filtering

Machine Vision Technology&#xff1a;Lecture2 Linear filtering Types of ImagesImage denoising图像去噪Defining convolution卷积的定义Key properties卷积的关键属性卷积的其它属性Annoying details卷积练习Sharpening锐化Gaussian KernelNoise噪声 分类Gaussian noise高…

Unity3D UnlitShader模板详解

前言 Unity3D UnlitShader模板是一种非常基础的着色器模板&#xff0c;它不考虑光照和阴影等效果&#xff0c;只关注物体的颜色和纹理。在一些简单的游戏或者特效中&#xff0c;使用UnlitShader可以提高渲染效率&#xff0c;同时也能够实现一些特殊的效果&#xff0c;比如描边、…

AI大模型的发展趋势?

大模型的发展趋势主要体现在以下几个方面&#xff1a; 1、模型规模的增长&#xff1a; 随着数据量和计算能力的不断增加&#xff0c;大型模型的规模也在不断扩大。模型参数数量、层数等指标不断刷新&#xff0c;以应对更复杂的任务和更大规模的数据。 2、多模态融合&#xff…

HTTP详解(HTTP的特点,状态码,工作原理,GET和POST的区别,如何解决无状态通信)!!!

文章目录 一、HTTP协议简介二、HTTP的主要特点三、HTTP之URL四、Request和Respons五、HTTP的状态码六、HTTP工作原理七、GET和POST请求的区别八、解决HTTP无状态通信——Cookie和Session 一、HTTP协议简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&…

iOS App冷启动优化:Before Main阶段

iOS应用冷启动时&#xff0c;在 UIApplicationMain(argc, argv, nil, appDelegateClassName)方法执行前&#xff0c;主要经历以下阶段&#xff1a; 1. 执行exec&#xff08;&#xff09;启动应用程序进程 2. 加载可执行文件&#xff0c;即将应用程序的Mach-O文件加载到内存…

WindowManagerService的addWindow方法源码解读

源码链接&#xff1a; https://cs.android.com/android/platform/superproject/main//main:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java;l9516?qsanitizeWindowType&hlzh-cn addWindow 方法如下&#xff1a; public int addWind…

31-树-找树左下角的值

这是树的第31篇算法&#xff0c;力扣链接。 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1 拿到这道题的第一想法&#xff0c;我可以层级遍历选取最左节点。 func f…

R语言数据可视化之美专业图表绘制指南(增强版):第1章 R语言编程与绘图基础

第1章 R语言编程与绘图基础 目录 第1章 R语言编程与绘图基础前言1.1 学术图表的基本概念1.1.1 学术图表的基本作用1.1.2基本类别1.1.3 学术图表的绘制原则 1.2 你为什么要选择R1.3 安装 前言 这是我第一次在博客里展示学习中国作者的教材的笔记。我选择这本书的依据是作者同时…

团体程序设计天梯赛 L2-002 链表去重

L2-002 链表去重 分数 25 给定一个带整数键值的链表 L&#xff0c;你需要把其中绝对值重复的键值结点删掉。即对每个键值 K&#xff0c;只有第一个绝对值等于 K 的结点被保留。同时&#xff0c;所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15&…

C#学习:初识各类应用程序

编写我们第一个程序——Hello,World! 1.编程不是“学”出来的&#xff0c;而是“练”出来的 2.在反复应用中积累&#xff0c;忽然有一天就会顿悟 3.学习原则&#xff1a; 3.1从感官到原理 3.2从使用别人的到创建自己的 3.3必需亲自动手 3.4必需学以致用&#xff0c;紧跟实际…

计算机网络原理--传输层

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 TCP/IP五层&#xff08;或四层&#xff09;模型 传输层 TCP和UDP的区别 UDP协议 校验和 如何…

c#压缩文件函数

/// <summary> /// 压缩文件 /// </summary> /// <param name"sourceFile">要压缩的文件名</param> /// <param name"destFile">压缩后的文件名</param> …

ORACLE EBS 润年日期漏入数据库处理

做之前记得做好备份表数据&#xff01; --1、 出错数据日期为&#xff1a;schedule_close_date 2024/2/28 Select * From inv.org_acct_periods Where period_set_name NIPRC_CALENDAR --根据自己的实际命名 And period_name FEB-24; --修正为&#xff1a;schedule_cl…

【Web】get请求和post请求的区别

get请求和post请求的区别 get请求请求参数在请求行中&#xff08;链接后面直接显式说明&#xff09;post请求请求参数在请求体中&#xff0c;通常以JSON形式传送 get请求可以直接看见明文post请求一般有加密 get请求的大小有限制post请求无限制 企业开发中&#xff0c;get经常被…

30天自制操作系统(第20天)

20.1 显示单个字符的API&#xff08;1&#xff09; 需要实现&#xff1a;当在命令窗口输入 ‘hlt’ 时&#xff0c;打印一个字符。思考一下&#xff0c;需要在执行hlt.nas文件时打印的字符&#xff0c;所以需要在文件中规定要打印的字符。打印字符需要调用cons_putchar函数&…

postcss-px-to-viewport include属性

包含include配置的(github)&#xff1a;npm i https://github.com/evrone/postcss-px-to-viewport -S 包含include配置的(npm)&#xff1a;npm i postcss-px-to-viewport-8-with-include -S 不包含包include配置的(npm)&#xff1a;npm i postcss-px-to-viewport 看了一下这篇文…

Linux 基础之 vmstat 命令详解

文章目录 一、前言二、使用说明2.1 vmstat [delay/count/d/D/t/w]2.2.vm模式的字段 一、前言 vmstat(VirtualMeomoryStatistics&#xff0c;虚拟内存统计)是一个不错的 Linux/Unix 监控工具&#xff0c;在性能测试中除了top外也是比较常用的工具之一&#xff0c;它可以监控操作…