【JDK8新特性之Stream流-Stream流常用的API以及案例实操】

news2025/7/19 11:16:03

JDK8新特性之Stream流,不知道你在投递简历的时候有没有看到JD(工作岗位要求去描述)上写到熟悉JDK中Stream流的相关使用。如果没有的话,接下来就和我一起学习一下吧

在这里插入图片描述

1.原始集合处理数据的弊端->Stream流优势之处,案例演示

  1. 自定义一个集合,集合中给定一些名字
  2. 获取所有姓李的信息
  3. 获取名字长度为2的人员
  4. 输出所有用户的信息
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class StreamDemo01 {

    public static void main(String[] args) {

        //1. 自定义一个集合,集合中给定一些名字
        List<String> list = Arrays.asList("李一一","李一","李二二","李二");
        //2. 获取所有姓李的信息
        ArrayList<String> list1 = new ArrayList<>();
        for(String str:list){
            if(str.startsWith("李")) list1.add(str);
            else continue;
        }
        //3. 获取名字长度为2的人员
        List<String> list2 = new ArrayList<>();
        for (String s : list1) {
            if(s.length() == 2) list2.add(s);
            else continue;
        }
        //4. 输出所有用户的信息
        for (String s : list2) {
            System.out.println(s);
        }
    }
}

上面的代码针对与我们不同的需求总是一次次的循环收集记过.这时我们希望有更加高效的处理方式,这时我们就可以通过JDK8中提供的Stream API来解决这个问题了。

演进为Stream的解决方案:

import java.util.Arrays;
import java.util.List;

public class StreamDemo02 {

    public static void main(String[] args) {
        //1. 自定义一个集合,集合中给定一些名字
        List<String> list = Arrays.asList("李一一","李一","李二二","李二");
        //2. 获取所有姓李的信息、过滤、输出
        list.stream()
                .filter(str->str.startsWith("李"))
                .filter(str-> str.length()==2)
                .forEach(s-> {System.out.println(s);});
    }
}

2. Steam流式思想概述

易错点

注意:Stream和IO流没有任何关系!

基本思想

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。如下图所示:
在这里插入图片描述

作用

Stream API能让我们快速完成许多复杂的操作,如筛选、切片、映射、查找、去除重复,统计,匹配和归约。

3. Stream流的获取方式

在来看获取Stream流方式的时候我们先来看一下Java集合框架结构。
在这里插入图片描述

3.1 根据Collection获取

​ 首先,java.util.Collection 接口中加入了default方法 stream,也就是说Collection接口下的所有的实现都可以通过steam方法来获取Stream流。

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.stream();
    Set<String> set = new HashSet<>();
    set.stream();
    Vector vector = new Vector();
    vector.stream();
}

​ Map接口没有实现Collection接口,这时我们可以根据Map获取对应的key value的集合。

public static void main(String[] args) {
    Map<String,Object> map = new HashMap<>();
    Stream<String> stream = map.keySet().stream(); // key
    Stream<Object> stream1 = map.values().stream(); // value
    Stream<Map.Entry<String, Object>> stream2 = map.entrySet().stream(); // entry
}

3.2 通过Stream的of方法

注意:基本数据类型的数组是不行的
在实际开发中我们不可避免的是会操作到数组中的数据,由于数组对象不可能添加默认方法,所有Stream接口中提供了静态方法of

public class StreamDemo{

    public static void main(String[] args) {
        Stream<String> stream1 = Stream.of("q", "w", "e");
        stream1.forEach(System.out::println);
        String[] arr1 = {"aa","bb","cc"};
        Stream<String> stream2 = Stream.of(arr1);
        stream2.forEach(System.out::println);
        Integer[] arr2 = {1,2,3,4};
        Stream<Integer> stream3 = Stream.of(arr2);
        stream3.forEach(System.out::println);
    }
}

4.Stream常用方法介绍

Stream流模型的常用方法很多,这里介绍一些常用的API。这些方法可以被分成两种:

方法名方法作用返回值类型方法种类
count统计个数long终结
forEach逐一处理void终结
filter过滤Stream函数拼接
limit取用前几个Stream函数拼接
skip跳过前几个Stream函数拼接
map映射Stream函数拼接
concat组合Stream函数拼接

终结方法:返回值类型不再是 Stream 类型的方法,不再支持链式调用。本小节中,终结方法包括 count 和 forEach 方法。

非终结方法:返回值类型仍然是 Stream 类型的方法,支持链式调用。(除了终结方法外,其余方法均为非终结方法。)

Stream注意事项(重要)

  1. Stream只能操作一次

  2. Stream方法返回的是新的流

  3. Stream不调用终结方法,中间的操作不会执行

4.1 forEach

Stream流中forEach用来遍历流中的数据,该方法接受一个Consumer接口,会将每一个流元素交给函数处理

	public static void main(String[] args) {
        Stream.of("硕", "风", "和").forEach(System.out::println);;
    }

4.2 count

Stream流中的count方法用来统计其中的元素个数的该方法返回一个long值,代表元素的个数。

public class StreamDemo {

    public static void main(String[] args) {
        long count = Stream.of(1, 2, 3,4,5).count();
        System.out.println(count);
    }
}

4.3 filter

filter方法的作用是用来过滤数据的。返回符合条件的数据,可以通过filter方法将一个流转换成另一个子集流,该接口接收一个Predicate函数式接口参数作为筛选条件

public class StreamDemo {

    public static void main(String[] args) {
         Stream.of(1, 2, 3,4,5,6)
                 .filter((s)->s>=3)
                 .forEach(System.out::println);

    }
}

输出:

在这里插入图片描述

4.4 limit

limit方法可以对流进行截取处理,支取前n个数据,参数是一个long类型的数值,如果集合当前长度大于参数就进行截取,否则不操作:

public class StreamDemo{

    public static void main(String[] args) {
        Stream.of(1, 2, 3,4,5,6)
                 .limit(3)
                 .forEach(System.out::println);

    }
}

输出:

在这里插入图片描述

4.5 skip

如果希望跳过前面几个元素,可以使用skip方法获取一个截取之后的新流,案例如下所示:

public class StreamDemo{

    public static void main(String[] args) {
        Stream.of(1, 2, 3,4,5,6)
                 .skip(3)
                 .forEach(System.out::println);

    }
}

输出:

在这里插入图片描述

4.6 map类型转换

如果我们需要将流中的元素映射到另一个流中,可以使用map方法:
该接口需要一个Function函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的数据

public class StreamDemo{

    public static void main(String[] args) {
        Stream.of(1, 2, 3,4,5,6)
                 .map(num->num.toString())
                 .forEach(System.out::println);

    }
}

4.7 sorted

如果需要将数据排序,可以使用sorted方法:
在使用的时候可以根据自然规则排序,也可以通过比较强来指定对应的排序规则

public class StreamDemo{

    public static void main(String[] args) {
         Stream.of("9", "6", "5","3","2","1","0")
                 .map(msg->Integer.parseInt(msg))
                 .sorted((o1,o2)->o1-o2)
                 .forEach(System.out::println);
    }
}

4.8 distinct

如果要去掉重复数据,可以使用distinct方法,案例如下:

public class StreamDemo {

    public static void main(String[] args) {
        Stream.of("9", "6","8", "5","3","2","2","1","0")
                 .map(Integer::parseInt)
                 .sorted((o1,o2)->o1-o2) 
                 .distinct() // 去掉重复的记录
                 .forEach(System.out::println);
    }
}

注意注意:Stream流中的distinct方法对于基本数据类型是可以直接出重的,但是对于自定义类型,我们是需要重写hashCode和equals方法来移除重复元素。

4.9 match

match是一个终结的方法
如果需要判断数据是否匹配指定的条件,可以使用match相关的方法
相关API如下

boolean anyMatch(Predicate<? super T> predicate); // 元素是否有任意一个满足条件
boolean allMatch(Predicate<? super T> predicate); // 元素是否都满足条件
boolean noneMatch(Predicate<? super T> predicate); // 元素是否都不满足条件

案例演示:

public class StreamDemo{

    public static void main(String[] args) {
        // 判断元素是否都大于3
        boolean b1 = Stream.of("9", "6", "8", "5", "3", "2", "2", "1", "0")
                .map(Integer::parseInt)
                .allMatch(s -> s > 3);
        System.out.println(b1);
        // 判断元素是否存在大于3的元素
        boolean b2 = Stream.of("9", "6", "8", "5", "3", "2", "2", "1", "0")
                .map(Integer::parseInt)
                .anyMatch(s -> s > 3);
        System.out.println(b2);
        // 判断元素是否都不大于3
        boolean b3 = Stream.of("9", "6", "8", "5", "3", "2", "2", "1", "0")
                .map(Integer::parseInt)
                .noneMatch(s -> s > 3);
        System.out.println(b3);
    }
}

4.10 find

如果我们需要找到某些数据,可以使用find方法来实现,如下面所示,案例如下:

public class StreamDemo{

    public static void main(String[] args) {

        Optional<String> first = Stream.of("1", "5", "1").findFirst();
        System.out.println(first.get());

        Optional<String> any = Stream.of("1", "1", "7").findAny();
        System.out.println(any.get());
    }
}

4.11 max和min

如果我们想要获取最大值和最小值,那么可以使用max和min方法,案例如下:

public class StreamDemo{

    public static void main(String[] args) {

        Optional<Integer> min = Stream.of("9", "6","8", "5","3","2","2","1","0")
                .map(Integer::parseInt)
                .min((o1,o2)->o2-o1);// 取来排序后第一个元素的位置为元素的最小值
        System.out.println(min.get());

        Optional<Integer> max = Stream.of("9", "6","8", "5","3","2","2","1","0")
                .map(Integer::parseInt)
                .max((o1,o2)->o2-o1);// 取来排序后最后一个元素的位置为元素的最大值
        System.out.println(max.get());
    }
}

4.12 reduce方法

如果需要将所有数据归纳得到一个数据,可以使用reduce方法,案例如下:

public class StreamDemo {

    public static void main(String[] args) {
        Integer sum = Stream.of("9", "6","8", "5","3","2","2","1","0")
                .map(Integer::parseInt)
                // 第一次的时候会将默认值赋值给x,以后每次将上一次的操作结果赋值给x y就是每次从数据中获取的元素
                .reduce(0, (x, y) -> {
                    //System.out.println("x:"+x+",y:"+y);
                    return x + y;
                });
        System.out.println(sum);
    }
}

4.13 map和reduce的组合

在实际开发中我们经常会将map和reduce一块来使用

public class StreamDemo {

    public static void main(String[] args) {
        // 1.求出所有年龄的总和
        Integer sumAge = Stream.of(
                new Person("a", 18)
                , new Person("b", 22)
        ).map(Person::getAge) // 实现数据类型的转换
                .reduce(0, Integer::sum);
        System.out.println(sumAge);

        // 2.求出所有年龄中的最大值
        Integer maxAge = Stream.of(
                new Person("a", 18)
                , new Person("b", 22)
        ).map(Person::getAge) // 实现数据类型的转换,符合reduce对数据的要求
                .reduce(0, Math::max); // reduce实现数据的处理
        System.out.println(maxAge);
        // 3.统计 字符 a 出现的次数
        Integer count = Stream.of("a", "b", "c", "d", "a", "c", "a")
                .map(ch -> "a".equals(ch) ? 1 : 0)
                .reduce(0, Integer::sum);
        System.out.println(count);
    }
}

4.14 mapToInt

如果需要将Stream中的Integer类型转换成int类型,可以使用mapToInt方法来实现,案例如下

public class StreamDemo{

    public static void main(String[] args) {
        // Integer占用的内存比int多很多,在Stream流操作中会自动装修和拆箱操作
        Integer arr[] = {7,4,3,6,7,3,4};
        // 为了提高程序代码的效率,我们可以先将流中Integer数据转换为int数据,然后再操作
        IntStream intStream = Stream.of(arr)
                .mapToInt(Integer::intValue);
        intStream.filter(i->i>3)
                .forEach(System.out::println);

    }
}

4.15 concat

如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat,案例如下:

public class StreamDemo{

    public static void main(String[] args) {
        Stream<String> stream1 = Stream.of("1","2","3");
        Stream<String> stream2 = Stream.of("3", "2", "1");
        Stream.concat(stream1,stream2).forEach(System.out::println);
    }
}

5. 总结

现在面试考察的范围越来越广,这就需要在平常的学习生活中不断的积累,等待厚积薄发的时候。
既然都看到这里了,那就留下你的关注吧,我是硕风和炜,我们下篇文章见哦!

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

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

相关文章

通过操作Cortex-A7核,串口输入相应的命令,控制LED灯进行工作增加编程要求

2.编程要求&#xff1a; 1&#xff09;结构体封装 typedef struct{ char* cmd_arr; //命令行字符串 gpio_t* gpiox;//GPIO组号 unsigned int pin; //引脚编号 status_t status; //LED灯状态 void(*gpio_write_pin)(gpio_t* gpiox,unsigned int pin,status_t status); }cmd_t; 2…

【GlobalMapper精品教程】054:标签(标注)功能案例详解

同ArcGIS标注一样,globalmapper提供了动态标注的功能,称为标签,本文详解标签的使用方法。 文章目录 一、标签配置二、创建标签图层三、标签图层选项1. 标签字段2. 标签样式3. 标签格式4. 标签语言5. 标签优先级一、标签配置 在配置页面的【矢量显示】→标签选项卡下,有标签…

《高性能MySQL》读书笔记(上)

目录 MySQL的架构 MySQL中的锁 MySQL中的事务 事务特性 隔离级别 事务日志 多版本并发控制MVCC 影响MySQL性能的物理因素 InnoDB缓冲池 MySQL常用的数据类型以及优化 字符串类型 日期和时间类型 数据标识符 MySQL的架构 默认情况下&#xff0c;每个客户端连接都…

Java高级编程之Lambda表达式

Lambda表达式 1&#xff0c;语法 利用Lambda 可以更简洁的实现匿名内部类与函数声明与调用&#xff1b;另外&#xff0c;基于Lambda 提供stream 流式处理极大简化对集合的操作 public static void main(String[] args) {//1.标准Lambda使用方式,其中MathOperation为定义的一个…

React 跨域的配置

1、为什么会出现跨域&#xff1f; 浏览器遵循同源政策&#xff08;同源策略三要素&#xff1a;协议相同、域名相同、端口相同&#xff09; 2、配置跨域代理 使用中间件 http-proxy-middleware&#xff08;安装依赖&#xff09; npm install http-proxy-middleware 创建setupP…

为什么需要这个岗位,软件测试是干什么

目录 一、软件测试概念 二、软件测试目的 三、软件测试基本原则 四、软件测试主要工作内容 五、软件测试方法 六、测试工程师的职责 七、为什么要软件测试这个岗位 一、软件测试概念 软件测试&#xff1a;为了发现软件错误和缺陷&#xff08;统称bug&#xff09;而执行…

网络协议(八):传输层-TCP(三次握手、四次挥手原理)

网络协议系列文章 网络协议(一)&#xff1a;基本概念、计算机之间的连接方式 网络协议(二)&#xff1a;MAC地址、IP地址、子网掩码、子网和超网 网络协议(三)&#xff1a;路由器原理及数据包传输过程 网络协议(四)&#xff1a;网络分类、ISP、上网方式、公网私网、NAT 网络…

拒绝摆烂!神仙网站Python自学,一路从入门闯到最后,边学边玩

前言给大家推荐3个边玩边学python的网站在刚接触编程&#xff0c;培养对其持续的兴趣是最最重要的事情辣&#xff01;&#xff01;&#xff01;因为前期需要大量的基础代码知识积累&#xff0c;这个过程对于不少人来说还是挺枯燥的&#xff0c;很有可能学到一半就放弃了&#x…

中电金信:金融数字化转型路在何方?这里有答案

近期&#xff0c;媒体大数网整合了业内10份研究报告&#xff0c;详解金融数字化转型的思路、方法与路径。其中「中国电子金融级数字底座“源启”白皮书」也被收录其中。让我们一同阅读文章&#xff0c;探究金融数字化转型相关问题的答案吧。 当前&#xff0c;金融科技正在回归…

大厂跟进ChatGPT,为什么百度“文心一言”成色最好?【快评】

作者 | 曾响铃 文 | 响铃说 赶ChatGPT热度&#xff0c;百度3月初就要发布与ChatGPT类似的人工智能聊天机器人服务“文心一言”&#xff08;英文名&#xff1a;ERNIE Bot&#xff09;&#xff0c;似乎无法提振资本市场对百度的信心。 2022年第四季度及全年未经审计的财报发布…

Python-基础知识

Python是什么 Python是计算机编程语言。 Python是解释型语言&#xff1a;Python在执行时&#xff0c;首先会将.py文件中的源代码转换成Python字节码&#xff0c;然后再由Python虚拟机来执行编译好的字节码。 名词解释 Python解释器&#xff08;Interpreter&#xff09;&#…

Text to image论文精读ALR-GAN:文本到图像合成的自适应布局优化

ALR-GAN是北京工业大学学者提出的一种自适应布局优化生成对抗网络&#xff0c;其可以在没有任何辅助信息的情况下自适应地优化合成图像的布局。 文章发表于2023年&#xff0c;IEEE Transactions on Multimedia&#xff08;TMM&#xff09;期刊&#xff08;CCF B&#xff0c;JCR…

基于Frenet优化轨迹的⾃动驾驶动作规划⽅法

动作规划&#xff08;Motion Control&#xff09;在⾃动驾驶汽⻋规划模块的最底层&#xff0c;它负责根据当前配置和⽬标配置⽣成⼀序列的动作&#xff0c;本⽂介绍⼀种基于Frenet坐标系的优化轨迹动作规划⽅法&#xff0c;该⽅法在⾼速情况下的ACC辅助驾驶和⽆⼈驾驶都具有较强…

浅谈MySQL索引

目录 1.索引的定义 2.索引的原理 3.Hash索引与B Tree索引 4.索引的分类 5.建立索引的注意事项 1.索引的定义 索引是存储引擎用于快速找到数据记录的一种数据结构&#xff0c;它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。 索…

python常见问题详解

Python python 没有多态&#xff0c;而是鸭子类型 多继承&#xff0c;没有接口&#xff0c;可通过语法糖实现接口的作用 lambda中只能有一句 "/"表示之前的参数是必须是位置参数&#xff0c;”**“表示是后面的必须是关键字参数 Python多进程 Python 多线程是伪多线…

ASE0510SH-ASEMI的MOS管ASE0510SH

编辑-Z ASE0510SH在SOT-89封装里的静态漏极源导通电阻&#xff08;RDS(ON)&#xff09;为140mΩ&#xff0c;是一款N沟道中低压MOS管。ASE0510SH的最大脉冲正向电流ISM为15A&#xff0c;零栅极电压漏极电流(IDSS)为1uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。ASE0510…

Mac电脑_GitHub提交项目至仓库

第一步&#xff08;准备工作&#xff09;&#xff1a; Mac 电脑自带 git &#xff0c; 无需安装 1. 创建一个项目 demo1 在 github 上 2. 创建 ssh 密钥 打开终端&#xff1a; ssh-keygen -t rsa -C "your_emailyouremail.com" 此处输入两次密码&#xff0c; 直接…

Linux-MYSQL 登录数据库(命令行,图形化) 及 远程登录

命令行登录 &#xff1a;mysql 命令登录数据库语法 &#xff1a; mysql -u用户名 -p密码 -h 连接的数据库服务器的ip [-D] 数据库名 -p 端口注 &#xff1a; 上面的 mysql 命令是指的是 客户端的指令 ~&#xff01;&#xff01;-h &#xff1a; 指的就是 连接数据库服务器的 ip…

并发编程学习篇ReentrantLock设计思想剖析

一、AQS原理剖析 什么是AQS java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为&#xff0c;比如 等待队列、条件队列、独占获取、共享获取等而这些行为的抽象就是基于AbstractQueuedSynchronizer&#xff08;简称AQS&#xff09;实现的&#xff0c;AQS是一…

如何使用开源 BI 工具 DataEase 实现系列数据分析呢?

当我们使用可视化分析工具制作仪表板时&#xff0c;可能需要制作的仪表板不是单个单个的可视化大屏&#xff0c;而是一系列的仪表板&#xff0c;我们需要用它来产生一个连续性的故事&#xff0c;那么这个时候我们该怎么办呢&#xff1f;例如说总分形式&#xff0c;我们需要一个…