java 不可变集合的创建和Stream流的使用

news2024/11/23 19:45:15

文章目录

    • 一、创建不可变的集合
      • 1.1为什么创建不可变的集合
      • 1.2 创建List、Set和Map的不可变集合
        • 1.2.1 创建List的不可变集合
        • 1.2.2 创建Set 的不可变集合
        • 1.2.3 创建Map的不可变集合
    • 二、使用集合 的Stream 流
      • 2.1 Stream的使用步骤
      • 2.2 Stream的方法
    • 三、如何获取Stream 流对象
    • 四、练习使用集合的Stream 流

一、创建不可变的集合

1.1为什么创建不可变的集合

  • 不可变集合是线程安全的,因为它们的状态在创建后不会改变。多个线程可以安全地共享和读取不可变集合,而无需同步。
  • 不可变集合不允许修改,可以安全地缓存和重用
  • 在多线程环境下使用 Stream 时,确保没有其他线程修改源集合

1.2 创建List、Set和Map的不可变集合

1.2.1 创建List的不可变集合
  • 方式一
public class Demo09 {
    public static void main(String[] args) {
        // 创建不可变的List集合
        List<String> list = List.of("张飞","关羽","刘备","曹操","孙权","孙尚香","吕布");

        // 增强for 循环 遍历
        for (String s : list){
            System.out.println(s);
        }

        // 迭代器 遍历
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        list.set(0,"张三"); // 集合不可修改,会报异常
    }
}
  • 方式二
public class Demo09 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("张飞","关羽","刘备","曹操","孙权","孙尚香","吕布");
        List<String> immutableList = Collections.unmodifiableList(list); // 设置不可变

        // 增强for 循环 遍历
        for (String s : immutableList){
            System.out.println(s);
        }

        // 迭代器 遍历
        Iterator<String> iterator = immutableList.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        immutableList.set(0,"张三"); // 集合不可修改会报异常
    }
}
1.2.2 创建Set 的不可变集合
public class Demo09 {
    public static void main(String[] args) {
        // 创建 Set 的不可变集合
        Set<String> set = Set.of("张飞","关羽","刘备","曹操","孙权","孙尚香","吕布");

        // 增强for 循环遍历
        for (String s : set){
            System.out.println(s);
        }

        //  迭代器遍历
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        set.add("诸葛亮"); // 不可变,报异常
    }
}
1.2.3 创建Map的不可变集合
  • 初版,不建议
public class Demo09 {
    public static void main(String[] args) {
        // 创建 Map的不可变集合 最多十个键值对,一般不用这种方式
        Map<String,Object> map1 = Map.of("姓名","张三","年龄",25,"地址","北京");

        // 创建不可变的Map 集合,元素个数不限
        Map<String,Object> map = new HashMap<>();
        map.put("姓名","李四");
        map.put("年龄",25);
        map.put("地址","北京");

        Set<Map.Entry<String,Object>> entrySet = map.entrySet();
        Map.Entry[] arr1 = new Map.Entry[0];
        // 底层会比较 entrySet 和arr1 的长度 ,长度不够会创建新的数组
        Map.Entry[] arrayEntry = entrySet.toArray(arr1); // Entry数组

        Map<String,Object> immutableMap  = Map.ofEntries(arrayEntry); // 不可变集合

        immutableMap.put("工资",10000); // 不支持修改,报异常
    }
}

  • 使用copyOf ,建议
public class Demo09 {
    public static void main(String[] args) {
        // 创建 Map的不可变集合 最多十个键值对,一般不用这种方式
        Map<String,Object> map1 = Map.of("姓名","张三","年龄",25,"地址","北京");

        // 创建不可变的Map 集合,元素个数不限
        Map<String,Object> map = new HashMap<>();
        map.put("姓名","李四");
        map.put("年龄",25);
        map.put("地址","北京");


        Map<String,Object> immutableMap = Map.copyOf(map); // 创建不可变的集合
        // 遍历方式一
        Set<String> ketSet = map.keySet();
        for (String key:ketSet){
            System.out.println(map.get(key));
        }

        // 遍历方式二
        Set<Map.Entry<String,Object>> entrySet = map.entrySet();
        for (Map.Entry entry: entrySet ){
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
        immutableMap.put("工资",10000); // 不可变,报异常
    }
}

二、使用集合 的Stream 流

2.1 Stream的使用步骤

获取到集合的Stream 流,相当于流水线 --> 把数据交给流处理 ,帅选,检查等 --> 流返回一个新的集合,流水线产品

  • 获取Stream 对象
  • 使用中间方法处理数据
  • 使用终结方法处理数据
  • 结合lambda表达式,简化操作
  • 终结方法一旦被调用,stream对象也就不可用了

2.2 Stream的方法

  • 常用处理方法(中间过程),返回Stream对象,链式调用
    图1
  • 终结方法,用于遍历,统计、获取新的集合等,一经调用后Stream 对象就不可用了
    图2

三、如何获取Stream 流对象

  • 单列集合(List/Set):使用stream方法
  • 双列集合(Map):不能直接获取,需要转换成Set
  • 数组:Arrays的静态方法stream
  • 一堆零散的数据:Stream 接口的静态方法of

四、练习使用集合的Stream 流

  • 案例一:统计集合中姓张的人数
public class Demo09 {
    public static void main(String[] args) {
        List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");

        long count = list.stream().filter(s->s.startsWith("张"))
                .count();
        System.out.println("姓张的总人数:" + count);
    }
}

  • 案例二:输出集合中所有姓张的人名
public class Demo09 {
    public static void main(String[] args) {
        List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");

        list.stream().filter(s->s.startsWith("张"))
                .forEach(s -> System.out.println(s));
    }
}
  • 案例三:输出前三个人的名字
public class Demo09 {
    public static void main(String[] args) {
        List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");

        list.stream().limit(3)
                .forEach(s -> System.out.println(s));
    }
}
  • 案例四:输出第四个人开始后面所有人的名字
public class Demo09 {
    public static void main(String[] args) {
        List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");

        list.stream().skip(3)
                .forEach(s -> System.out.println(s));
    }
}

  • 案例五:去除重复的人名
public class Demo09 {
    public static void main(String[] args) {
        List<String> list = List.of("刘备","刘备","关羽","曹操","张飞","李四","张苞");

        list.stream().distinct()
                .forEach(s -> System.out.println(s));
    }
}
  • 案例六:合并两个集合
public class Demo09 {
    public static void main(String[] args) {
        List<String> list1 = List.of("刘备","刘备","关羽","曹操","张飞","李四","张苞");

        List<String> list2 = List.of("王五","刘六");

        Stream<String> stringStream =  Stream.concat(list1.stream(),list2.stream());
        stringStream.forEach(s -> System.out.println(s));

    }
}
  • 案例七:将集合的结果保存到数组中
public class Demo09 {
    public static void main(String[] args) {
        List<String> list1 = List.of("刘备","刘备","关羽","曹操","张飞","李四","张苞");

        Object[] objects =  list1.stream()
                            .distinct()
                            .limit(3)
                            .toArray();
        for (Object o : objects){
            System.out.println(o.toString());
        }
    }

  • 案例八:将Stream的处理结果放到集合中
public class Demo09 {
    public static void main(String[] args) {
        List<String> list1 = List.of("刘备", "刘备", "关羽", "曹操", "张飞", "李四", "张苞");

        // 方式一:不指定具体类型的数组
//        Object[] objects = list1.stream()
//                .distinct()
//                .limit(3)
//                .toArray();
//        System.out.println(Arrays.toString(objects));


        // 方式二:指定类型的数组
        String arr[] = list1.stream().toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });
        System.out.println(Arrays.toString(arr));
    }
}

改成Lamda 表达式

public class Demo09 {
    public static void main(String[] args) {
        List<String> list1 = List.of("刘备", "刘备", "关羽", "曹操", "张飞", "李四", "张苞");

        // 方式一:不指定具体类型的数组
//        Object[] objects = list1.stream()
//                .distinct()
//                .limit(3)
//                .toArray();
//        System.out.println(Arrays.toString(objects));


        // 方式二:指定类型的数组
        String arr[] = list1.stream().toArray(value -> new String[value]);
        System.out.println(Arrays.toString(arr));
    }
}
  • 将数据收集到集合中
public class Demo09 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList,"张三丰-男-99","周芷若-女-25","张无忌-男-21");
        Collections.unmodifiableList(arrayList);// 设置为不可变的集合

        // 需求1:把所有的男性收集起来,放到一个List集合中
//        List<String> newList = arrayList.stream().filter(new Predicate<String>() {
//            @Override
//            public boolean test(String s) {
//                return s.contains("男");
//            }
//        }).collect(Collectors.toList());
//    }

    // 需求2:把所有的男性收集起来,放到一个Set集合中
//    Set<String> stringSet = arrayList.stream().filter(s -> s.contains("男"))
//            .collect(Collectors.toSet());
//    System.out.println(stringSet);

    /* 需求3:把所有的男性收集起来,放到一个Map集合中,姓名为键,年龄为值
     toMap的两个参数:参数一:表示键的生成规则,参数二表示值的生成规则
     Function<T, R>的两个参数,T 表示流的数据类型,即apply的参数类型;R表示返回的数据类型,即apply的返回类型
     重要:键不能重复
    */

    Map<String,Integer> map = arrayList.stream()
            .filter(s -> "男".equals(s.split("-")[1]))
            .collect(Collectors.toMap(new Function<String, String>() { // 键的生成规则
                                          @Override
                                          public String apply(String s) {
                                              return s.split("-")[0];
                                          }
                                      },
                    new Function<String, Integer>() { // 值的生成规则
                        @Override
                        public Integer apply(String s) {
                            return Integer.parseInt(s.split("-")[2]);
                        }
                    }));
        System.out.println(map);
        }
}

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

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

相关文章

使用 GCD 实现属性的多读单写

使用 Grand Central Dispatch (GCD) 实现多读单写的属性 首先需要确保在多线程环境下的线程安全性。可以使用 GCD 提供的读写锁机制 dispatch_rwlock_t 或者 dispatch_queue_t 来实现这个功能。 Swift版本的实现 怎样创建一个并发队列 &#xff1f;// 使用 Swift 来实现的首…

swift使用swift-protobuf协议通讯,使用指北

什么是Protobuf Protobuf&#xff08;Protocol Buffers&#xff09;协议&#x1f609; Protobuf 是一种由 Google 开发的二进制序列化格式和相关的技术&#xff0c;它用于高效地序列化和反序列化结构化数据&#xff0c;通常用于网络通信、数据存储等场景。 为什么要使用Proto…

(四)主成分分析和因子分析法基础练习题(17道选择题)

本文整理了主成分分析和因子分析法相关的练习题&#xff0c;共17道&#xff0c;适用于想巩固理论基础的同学。来源&#xff1a;如荷学数据科学题库&#xff08;CDA二级-宏观业务分析方法&#xff09;。 1&#xff09; 2&#xff09; 3&#xff09; 4&#xff09; 5&#xff09…

5千关打乱汉字选择成语题ACCESS\EXCEL数据库

成语类的游戏之所有很火&#xff0c;最大的原因是门槛低&#xff0c;读过小学的人几乎都可以尝试过几关&#xff0c;之前发过《885成语错别字选择题库》、《638成语错别字题库》、《7千8百多条成语填空选字》、《3600关成语填字APP游戏》、《600多个看图猜成语成语图片》《315四…

HMI之王 STM32H7S7

还要什么自行车啊 感谢原厂精彩培训和慷慨赠板&#xff01; 以下列示几个关注的点&#xff0c;计划做成系列&#xff0c;随缘更新&#xff0c;尽量填。 0&#xff09;1024*600分辨率配5寸触屏&#xff1b;Type-C with USB 2.0 HS interface, dual‑role‑power 终于不用2根线…

基于STM32的智能水产养殖系统(四)

硬件原理 步进电动机 步进电动机&#xff08;Step Motor 或 Stepper Motor&#xff09;是一种将电脉冲信号转换成对应的角位移或线位移的电动机。与普通电动机不同&#xff0c;步进电动机每接收到一个脉冲信号&#xff0c;就会按设定的角度&#xff08;步距角&#xff09;转动…

【git】gitee仓库本地克隆失败可能的一种解决办法

出错点&#xff1a; 在 gitee 克隆远程仓库到 本地时&#xff0c;可能会出现以下报错情况&#xff0c;无法成功克隆 正常流程&#xff1a;&#xff08;熟悉正常克隆流程的可以直接跳到下面的【解决办法】&#xff09; 我们一般复制仓库地址是在下面红线框框的位置&#xff0c…

R语言统计分析——数据管理1

参考资料&#xff1a;R语言实战【第2版】 创建分析用数据集&#xff1a; manager<-c(1,2,3,4,5) date<-c(10/24/08,10/28/08,10/1/08,10/12/08,5/1/09) country<-c(US,US,UK,UK,UK) gender<-c(M,F,F,M,F) age<-c(32,45,25,39,99) q1<-c(5,3,3,3,2) q2<-c…

解决ERROR: Cannot uninstall ‘ipython-genutils‘.的方法

删除ipython-genutils-X-pyX.egg-info文件&#xff0c;X表示对应版本&#xff0c;问题解决。

杨辉三角的快速求法

一、杨辉三角形 杨辉三角形&#xff0c;又称贾宪三角形&#xff0c;帕斯卡三角形&#xff0c;是二项式系数在三角形中的一种几何排列&#xff0c;是二项式系数在三角形中的一种几何排列&#xff0c;古称“开方作法本源图”。 杨辉三角的历史 北宋人贾宪约1050年首先使用“贾…

搭建musetalk数字人的步骤

生成数字人的视频效果 搭建步骤 下载git代码 git clone https://github.com/TMElyralab/MuseTalk.git创建conda环境 (建议使用 python 版本 >3.10 和 cuda 版本 11.7。) conda create -n musetalk python3.10进入conda环境 conda activate musetalk下载项目依赖包 pip…

如何理解光学中的群速度和相速度。

我不太明白为什么书上要区分相速度和群速度&#xff0c;不管这个&#xff0c;我想看看这两个速度在真实周期函数上的影响是如何的。 首先计算&#xff0c;直接计算三角函数我不会&#xff0c;利用复数做&#xff0c;可以取的实部。其中&#xff0c;。。 这个公式说明了什么呢…

Neo4j 创建关系

Neo4j 创建关系 在 Noe4j 中&#xff0c;关系是我们用来连接图的两个节点的元素。 这些关系具有数据的方向、类型和形式模式。 本章教你如何 建立关系在现有节点之间创建关系使用标签和属性创建关系 建立关系 我们可以使用 CREATE 子句创建关系。 我们将在方括号[]中指定关系…

后方穿行预警系统技术规范(简化版)

后方穿行预警系统技术规范(简化版) 1 系统概述2 预警区域3 预警目标4 预警条件5 指标需求1 系统概述 RCTA后方穿行预警系统工作在驾驶员有倒车意向的时候。在倒车过程中当驾驶员视线因周围障碍物被遮挡而产生碰撞风险时,系统通过光学信号对驾驶员进行提醒。 2 预警区域 RCT…

一个关于空格的Sql Server面试题

先上题目&#xff1a; 回答下面sql 的输出结果 declare s1 varchar(10) declare s2 varchar(10) set s1a b set s2a b if s1s2 select true 答案是 true 那么上面的 s1 和 s2 是否相等的呢&#xff1f; 我们再看看下面的sql declare s1 varchar(10) declare s2 varchar…

# [0619] Task01 绪论、马尔可夫过程、动态规划

easy-rl PDF版本 笔记整理 P1 - P2 joyrl 比对 补充 P1 - P3 相关 代码 整理 最新版PDF下载 地址&#xff1a;https://github.com/datawhalechina/easy-rl/releases 国内地址(推荐国内读者使用)&#xff1a; 链接: https://pan.baidu.com/s/1isqQnpVRWbb3yh83Vs0kbw 提取码: us…

xcode和iPhone真机或者watch真机连接问题

1.如果真机是第一次连接xocde&#xff0c;就需要开启真机上的开发者模式&#xff0c;开启开发者模式的方式&#xff1a; iphone/ipad开启方式: 设置 > 隐私与安全 > 开发者模式 > 开启&#xff0c;然后重启就可以了 watch设置&#xff1a;很麻烦&#xff0c;看文章…

Hive期末总结

hive的概念&#xff0c;谁开发的 Apache Hive 是一个Apache 软件基金会维护的开源项目 Facebook贡献 hive是一个基于hadoop的数据仓库工具&#xff08;对数据汇总查询和分析的工具&#xff09; hive执行原理 Hive通过给用户提供的一系列交互接口&#xff0c;接收到用户的指令…

Leetcode3179. K 秒后第 N 个元素的值

Every day a Leetcode 题目来源&#xff1a;3179. K 秒后第 N 个元素的值 解法1&#xff1a;模拟 模拟 k 轮&#xff0c;数组保存上一次结果&#xff0c;然后计算当前轮次的结果。 代码&#xff1a; /** lc appleetcode.cn id3179 langcpp** [3179] K 秒后第 N 个元素的值…

自然语言处理概述

目录 1.概述 2.背景 3.作用 4.优缺点 4.1.优点 4.2.缺点 5.应用场景 5.1.十个应用场景 5.2.文本分类 5.2.1.一般流程 5.2.2.示例 6.使用示例 7.总结 1.概述 自然语言处理&#xff08;NLP&#xff09;是计算机科学、人工智能和语言学的交叉领域&#xff0c;旨在实…