Stream 流常见基本操作

文章目录

  • 概述
    • 一、Stream 流的常见生成方式
    • 二、Stream 流中间操作方法
      • 1、常用中间操作方法
      • 2、使用示例1
      • 3、使用示例2
      • 4、使用示例3
      • 5、使用示例4
      • 6、使用示例5
      • 7、Stream 流使用注意事项
    • 三、Stream 流终结操作方法
      • 1、常用终结方法
      • 2、使用示例1
      • 3、使用示例2
      • 4、使用示例3
      • 5、Stream 基本分组功能
    • 四、Stream 综合小练习
  • 小结

概述

Stream 流是 Java8 新特性之一,我们在实际开发中借助 Stream 流搭配 Lambda 表达式,可以很方便的完成一些对集合的操作,可以显著的提升开发的效率和性能。

一、Stream 流的常见生成方式

通常我们会选择对以下类型生成 Stream 流:单列集合、双列集合、数组、零散的数据。

public class StreamDemo {
    public static void main(String[] args) {
        //Collection体系的集合可以使用默认方法stream()生成流
        List<String> list = new ArrayList<String>();
        Stream<String> listStream = list.stream();

        Set<String> set = new HashSet<String>();
        Stream<String> setStream = set.stream();

        //Map体系的集合间接的生成流
        Map<String,Integer> map = new HashMap<String, Integer>();
        Stream<String> keyStream = map.keySet().stream();
        Stream<Integer> valueStream = map.values().stream();
        Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

        //数组可以通过Arrays中的静态方法stream生成流
        String[] strArray = {"hello","world","java"};
        Stream<String> strArrayStream = Arrays.stream(strArray);
      
      	//同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
        Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
        Stream<Integer> intStream = Stream.of(10, 20, 30);
    }
}

二、Stream 流中间操作方法

1、常用中间操作方法

这里的中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作(其他中间操作或终结操作)

方法名说明
Stream filter(Predicate predicate)用于对流中的数据进行过滤
Stream limit(long maxSize)获取前几个元素
Stream skip(long n)跳过前几个元素
Stream distinct()元素去重,依赖(hashCode和equals方法)
Stream sorted(Comparator<? super T> comparator)Stream 流元素排序
static Stream concat(Stream a, Stream b)合并a和b两个流为一个流
Stream map(Function<T,R> mapper)转换流中的数据类型

Stream.contact 合并两个 stream 流的时候,如果一个 stream 是 a 类型,另一个 stream 是 b 类型,那么最终合并为 a,b的父类型(类型提升)。

2、使用示例1

public class FilterDemo {
	// 获取以张开头的元素
    public static void main(String[] args) {
    	 // 创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<>();
        list.add("张三丰");
        list.add("张无忌");
        list.add("张翠山");
        list.add("王二麻子");
        list.add("张良");
        list.add("谢广坤");

        list.stream().filter(s ->s.startsWith("张")).forEach(s-> System.out.println(s));

    }
}

3、使用示例2

public class LimitAndSkipDemo {
    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));
    }
}

4、使用示例3

public class SortedDemo {
	// 按照年龄进行排序
    public static void main(String[] args) {
        ArrayList<String> manList = new ArrayList<>();
        Collections.addAll(manList,"蔡坤坤,24","叶厚贤,23,","刘不甜,22","吴倩,24","谷加,30","肖亮亮,27");

        manList.stream()
                .sorted((o1,o2)->Integer.parseInt(o1.split(",")[1]) - Integer.parseInt(o2.split(",")[1]))
                .forEach(x -> System.out.println(x));
    }
}

5、使用示例4

public class ConcatAndDistinctDemo {
    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).distinct().forEach(s-> System.out.println(s));
    }
}

6、使用示例5

public class MapDemo {
    public static void main(String[] args) {

        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"张无忌-15","周芷若-14","赵敏-13","张强-20","张三丰-100","张翠山-40");

        // 需求:只获取里面1的年龄并进行打印
        List<Integer> collect = list.stream()
                .map(s -> Integer.parseInt(s.split("-")[1]))
                .collect(Collectors.toList());
        System.out.println(collect);

    }
}

7、Stream 流使用注意事项

注意1:修改 Stream 流中的数据,不会影响原来集合或者数组中的数据。

注意2:中间方法,返回新的 Stream 流,原来的 Stream 流只能使用一次,建议使用链式编程()。因为每次调用中间方法都会返回新的 Stream 流,原来的 Stream 流会关闭。如:

public class Test1 {
    public static void main(String[] args) {

        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        Stream<String> stream1 = list.stream().filter(s -> s.startsWith("张"));
        Stream<String> stream2 = stream1.filter(s -> s.length() == 3);
        stream2.forEach(s -> System.out.println(s));

        stream1.filter(s -> s.length() == 2);
    }
}

三、Stream 流终结操作方法

1、常用终结方法

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

方法名说明
void forEach(Consumer action)遍历
long count()统计个数
toArray()收集流中的数据,放到数组中
R collect(Collector collector)收集流中的数据,放到集合中

工具类 Collectors 提供了具体的收集方式:

方法名说明
public static Collector toList()把元素收集到List集合中
public static Collector toSet()把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper)把元素收集到Map集合中

注意1toSet() 会进行自动去重。
注意2toMap() 如果我们要收集到 Map 集合当中,键重复会报错。

2、使用示例1

public class CountAndForEachDemo {
    public static void main(String[] args) {
    
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<>();
        list.add("张三丰");
        list.add("张无忌");
        list.add("张翠山");
        list.add("王二麻子");
        list.add("张良");
        list.add("谢广坤");


        // 统计返回此流中的元素数
        long count = list.stream().count();
        System.out.println(count);

        // 遍历打印流中元素
        list.stream().forEach(x -> System.out.println(x));

    }
}

3、使用示例2

public class ToArrayDemo {
    public static void main(String[] args) {
    
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<>();
        list.add("张三丰");
        list.add("张无忌");
        list.add("张翠山");
        list.add("王二麻子");
        list.add("张良");
        list.add("谢广坤");

        // 收集流中的数据,放到数组中 (Object 数组)
        Object[] objects = list.stream().toArray();
        System.out.println(Arrays.toString(objects));

        // 收集流中的数据,放到数组中 (指定类型 数组)
        // toArray 方法参数就是创建一个指定类型的数组
        // 底层会依次得到流里面的每一个数据,并把数据放到数组当中
        // 返回值就是一个装着流里面所有数据的数组
        String[] strings = list.stream().toArray(valuecount -> new String[valuecount]);
        System.out.println(Arrays.toString(strings));

    }
}

4、使用示例3

public class CollectDemo {
    public static void main(String[] args) {

        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"张无忌-男-15","周芷若-女-14","赵敏-女-13","张三丰-男-100","谢广坤-男-41");

        // 需求1:把所有男性收集到list集合当中
        List<String> newList1 = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toList());
        System.out.println(newList1);

        // 需求2:把所有男性收集到set集合当中
        Set<String> newList2 = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toSet());
        System.out.println(newList2);

        // 需求3:把所有男性收集到map集合当中(键为姓名,值为年龄)
        Map<String, Integer> map = list.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toMap(
                        s -> s.split("-")[0],
                        s -> Integer.parseInt(s.split("-")[2])));
        System.out.println(map);
    }
}

5、Stream 基本分组功能

方法名说明
Collector<T, ?, Map<K, List>> groupingBy(Function<? super T, ? extends K> classifier)这是最基本的 groupingBy 方法,classifier:键映射:该方法的返回值是键值对的 键
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream)这个重载方法在基本的 groupingBy 方法的基础上添加了一个 downstream 参数,downstream:值映射:通过聚合方法将同键下的结果聚合为指定类型,该方法返回的是键值对的 值
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier mapFactory, Collector<? super T, A, D> downstream)这个重载方法除了包含分类函数和 downstream 收集器外,还接收一个 mapFactory 参数,mapFactory:无参构造函数提供返回类型:提供一个容器初始化方法,用于创建新的 Map容器 (使用该容器存放值对)
public class GroupDemo {
	// 基本分组操作
    public static void main(String[] args) {
        // 初始化数据
        Actor actor1 = new Actor("张三",18);
        Actor actor2 = new Actor("李四",20);
        Actor actor3 = new Actor("王五",22);
        List<Actor> actors = new ArrayList<>();
        Collections.addAll(actors,actor1,actor2,actor3);
        // 按照姓名分组
        Map<String, List<Actor>> collect = actors.stream().collect(Collectors.groupingBy(actor -> actor.getName()));
        // 打印结果
        System.out.println(collect);

        // 将不同课程的学生进行分类
        Map<String, List<Actor>> groupByCourse = actors.stream().collect(Collectors.groupingBy(actor -> actor.getName()));
        System.out.println(groupByCourse
        );
        Map<String, List<Actor>> groupByCourse1 = actors.stream().collect(Collectors.groupingBy(actor -> actor.getName(), Collectors.toList()));
        System.out.println(groupByCourse1);

        // 上面的方法中容器类型和值类型都是默认指定的,容器类型为:HashMap,值类型为:ArrayList
        // 可以通过下面的方法自定义返回结果、值的类型
        Map<String, List<Actor>> groupByCourse2 = actors.stream()
                .collect(Collectors.groupingBy(actor -> actor.getName(),
                        () -> new HashMap<>(),
                        Collectors.toList()));
        System.out.println(groupByCourse2);
    }
}

其他分组操作参考:Stream Collectors.groupingBy 的四种用法

四、Stream 综合小练习

public class Test {
    public static void main(String[] args) {
        // 现有两个 ArrayList 集合:
        // 第一个集合:存储 6 名男演员的名字和年龄;第二个集合:存储 6 名女演员的名字和年龄
        ArrayList<String> manList = new ArrayList<>();
        ArrayList<String> womanList = new ArrayList<>();
        Collections.addAll(manList,"蔡坤坤,24","叶厚贤,23,","刘不甜,22","吴倩,24","谷加,30","肖亮亮,27");
        Collections.addAll(womanList,"赵晓英,35","杨颖,36","高媛媛,43","刘诗,35","杨小敏,33");

        // 需求1:男演员只要名字为 3 个字的前两人
        Stream<String> stream1 = manList.stream().filter(s -> s.split(",")[0].length() == 3)
                .limit(2);

        // 需求2:女演员只要姓杨的,并且不要第一个
        Stream<String> stream2 = womanList.stream().filter(s -> s.split(",")[0].startsWith("杨"))
                .skip(1);

        // 需求3:把过滤后的男演员姓名和女演员合并到一起封装成 Actor 对象(Actor 对象属性有 name、age)
        Stream<Actor> stream3 = Stream.concat(stream1, stream2)
                .map(s -> new Actor(s.split(",")[0], Integer.parseInt(s.split(",")[1])));

        // 需求5:将所有的演员对象都报存到 List 集合中
        stream3.collect(Collectors.toList()).forEach(s -> System.out.println(s));

    }
}

小结

Stream 流的使用步骤?

  1. 获取 Stream 流对象
  2. 使用中间方法处理数据
  3. 使用终结方法处理数据

如何获取 Stream 流对象?

  1. 单列集合:Collection 中的默认方法
  2. 双列集合:不能直接获取,可借助 keySets、values 转换成单列集合间接获取
  3. 数组:Arrays 工具类型中的静态方法
  4. 零散的数据:Stream 接口中的静态方法 of

Stream 常见方法?

  1. 中间方法:filter、limit、skip、distinct、concat、map
  2. 终结方法:forEach、count、collect

Lambda 怎么简化?

  1. 首先,数据类型可以省略
  2. 如果形参只有一个,小括号可以省略
  3. 如果形参有多个,小括号就不能省略了
  4. 如果方法体只有一行,那么大括号可以省略,return 可以省略分号可以省略

:上述所有方法皆为函数式接口,因此均可以使用 Lambda 表达式进行替换,或使用方法引用替换(下期介绍)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

界面控件DevExpress Blazor UI v23.2 - 浅谈增强的可访问性

DevExpress Blazor UI组件库提供了一套全面的原生Blazor组件(包括DataGrid、Pivot Grid、 调度程序、图表、数据编辑器和报表)&#xff0c;使用C#为Blazor Server和Blazor WebAssembly创建高影响力的用户体验&#xff01; 获取DevExpress v23.2正式版下载(Q技术交流&#xff1…

【Linux开发 第三篇】vmtools安装,快照

虚拟机克隆 方式一 直接拷贝一份安装好的虚拟机文件&#xff0c;再用VM打开文件即可 方式二 使用vmware的克隆操作&#xff08;克隆时要先关闭Linux系统&#xff09; 虚拟机快照 如果你在使用虚拟机的时候&#xff0c;担心现在的操作&#xff0c;想回到操作之前的状态&a…

开放式耳机哪个牌子好?热门开放式耳机合集,买前必看!

随着人们对运动健康的重视&#xff0c;越来越多的运动爱好者开始关注如何在运动中享受音乐。开放式蓝牙耳机凭借其独特的设计&#xff0c;成为了户外运动的理想选择。它不仅让你在运动时能够清晰听到周围环境的声音&#xff0c;保持警觉&#xff0c;还能让你在需要时与他人轻松…

08 JavaScript学习:数据类型

JavaScript 数据类型 值类型(基本类型)&#xff1a;字符串&#xff08;String&#xff09;、数字(Number)、布尔(Boolean)、空&#xff08;Null&#xff09;、未定义&#xff08;Undefined&#xff09;、Symbol。 引用数据类型&#xff08;对象类型&#xff09;&#xff1a;对…

插入排序与希尔排序

文章目录 插入排序配图详解核心思想核心代码 源代码运行结果 希尔排序实现逻辑源代码运行结果 插入排序 插入排序在少量数据中是一个高效的算法&#xff0c;你可以想象在打牌的时候&#xff0c;左手是已经整理好的牌&#xff0c;右手是正在抓取的牌。 配图详解 对一组数据 5&…

手机号码空号过滤API:有效验证和过滤无效电话号码

随着移动通信技术的发展&#xff0c;手机号码成为人们日常生活和工作中不可或缺的一部分。然而&#xff0c;随着时间的推移&#xff0c;一些手机号码可能会变成空号&#xff0c;这给企业在进行电话营销和数据分析时带来了一定的困扰。为了解决这个问题&#xff0c;挖数据平台提…

武汉星起航:引领跨境电商新潮流,一站式孵化助力卖家轻松出海

武汉星起航电子商务有限公司&#xff0c;作为跨境电商领域的领军者&#xff0c;始终秉持“走出去”的战略理念&#xff0c;依托自营店铺的丰富经验和对跨境电商资源的深度整合&#xff0c;成功打造了一站式卖家孵化体系。这一体系集开店策划、运营教学、资源服务于一体&#xf…

Linux:常用软件、工具和周边知识介绍

上次也是结束了权限相关的知识&#xff1a;Linux&#xff1a;权限相关知识详解 文章目录 1.yum-管理软件包的工具1.1基本介绍1.2yum的使用1.3yum的周边生态1.4软件包介绍 2.vim-多模式的文本编辑器2.1基本介绍2.2基本模式介绍2.2.1命令模式&#xff08;Normal mode&#xff09;…

SpringBoot项目如何实现邮件发送

文章目录 1. 开启邮箱SMTP服务2. 导入pom依赖3. 在配置文件中添加邮箱配置3. 封装EmailTask类4. 写测试类 1. 开启邮箱SMTP服务 这里以163邮箱为例&#xff0c;点击设置——更多设置——POP3/SMTP/IMAP——开启服务 根据提示开启服务之后会得到一个授权码&#xff0c;只显示一…

七牛云配置,图片上传、查看的使用(备忘)

修改配置文档 修改新创建的空间的地区名 访问设置为 公开&#xff0c;不然会有访问时间限制 检查 上传和查看的链接是否正确。

Llama3本地部署实现模型对话

1. 从github下载目录文件 https://github.com/meta-llama/llama3 使用git下载或者直接从github项目地址下载压缩包文件 git clone https://github.com/meta-llama/llama3.git2.申请模型下载链接 到Meta Llama website填写表格申请,国家貌似得填写外国,组织随便填写即可 3.…

STL容器搜索:当直接访问STL容器时,如何执行有效和正确的搜索?

掌握STL容器搜索技巧:在C中实现高效和准确的数据访问 一、简介二、std::vector, std::deque, std::list三、std::map, std::multimap, std::set, std::multiset四、std::string六、总结 一、简介 本文主要了解如何在直接访问c容器时高效地进行搜索。在STL容器中搜索&#xff0…

【PostgreSQL里insert on conflict do操作时的冲突报错分析】

最近在巡检PostgreSQL的数据库的时候&#xff0c;发现部分数据库里存在大量的如下报错 ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time HINT: Ensure that no rows proposed for insertion within the same command have duplicate constrained val…

如何在CentOS本地搭建DataEase数据分析服务并实现远程查看数据分析

文章目录 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 前言 DataEase 是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务…

信息系统项目管理师0056:数据管理(4信息系统管理—4.2管理要点—4.2.1数据管理)

点击查看专栏目录 文章目录 4.2管理要点4.2.1数据管理1.数据战略2.数据治理3.数据架构4.数据应用5.数据安全6.数据质量7.数据标准8.数据生存周期9.理论框架与成熟度4.2管理要点 信息系统管理涉及系统准备、设计、实施、运行等活动的众多方面,

基于SpringBoot的在线五子连珠的设计与实现,前端采用vue框架;后端采用SpringBoot,mybatis

介绍 基于SpringBoot的在线五子连珠的设计与实现&#xff0c;主要是设计一款五子棋游戏&#xff0c;涉及登录注册的功能&#xff0c;人机对战、联机对战和积分排行榜的功能。其中人机对战中&#xff0c;电脑采用的是采用了一种基于局面分析的评分算法来确定机器人的下一步落子…

java 红黑树

01.红黑树的定义&#xff1a; 每一个结点有五个属性&#xff1a;

书生浦语大模型实战训练营--第二期第六节--Lagent AgentLego 智能体应用搭建--homework

一、基础作业 1.完成 Lagent Web Demo 使用&#xff0c;并在作业中上传截图 根据以下命令启动成功&#xff01; 2.完成 AgentLego 直接使用部分&#xff0c;并在作业中上传截图 这是原图 使用AgentLego进行自动目标检测后&#xff0c;很明显图中的物体已经被识别出来了 二、…

ElasticSearch可视化工具:kibana + elasticsearch-head

kibana 下载 地址&#xff1a;https://www.elastic.co/cn/downloads/kibana 下载别的版本&#xff1a;https://www.elastic.co/cn/downloads/past-releases#kibana 将Kibana安装包解压缩 进入config目录&#xff0c;在kibana.yml中添加es服务器地址。&#xff08;如果之前没…

Latex使用algoritm2e出现的错误汇总(updating)

1. return 和 end在一行 解决办法是&#xff1a;\Return{}中必须使用latex公式&#xff0c;如&#xff1a;\Return{$S_b$}
最新文章