Springboot 错用list.stream , 遭遇list浅拷贝偷袭,实战图解

news2024/11/25 3:56:47

前言

相信很多看客都听闻过深拷贝、浅拷贝  , 但是在日常使用的过程中,是否真的有关心过或者遭遇过呢?

不啰嗦,一起来看看。

正文

接下来我通过示例,来复现一下 list.stream浅拷贝 这个事 :

首先是一个对象 Product :
 

/**
 * 产品
 */
@Data
public class Product {

    /**
     * 级别
     */
    private Integer level;
    /**
     * 售价
     */
    private BigDecimal amount;
    /**
     *  库存
     */
    private Long  stockNum;


}

然后是模拟获取到的这个Product的一个list集合数据:
 

    private static  List<Product> getTestList() {
      List<Product> products=new ArrayList<>();
        Product product1=new Product();
        product1.setLevel(100);
        product1.setAmount(new BigDecimal("100"));
        product1.setStockNum(100L);

        Product product2=new Product();
        product2.setLevel(200);
        product2.setAmount(new BigDecimal("200"));
        product2.setStockNum(200L);

        Product product3=new Product();
        product3.setLevel(300);
        product3.setAmount(new BigDecimal("300"));
        product3.setStockNum(300L);

        products.add(product1);
        products.add(product2);
        products.add(product3);
        return products;
    }

接下来做什么, 比如说,我们对这list数据进行按照金额排序输出 以及按照 库存排序输出。

使用了   list.stream().sorted(xxx).collect(Collectors.toList())     

    public static void main(String[] args) {

        List<Product> testList = getTestList();

        List<Product> amountSortList = testList.stream()
                .sorted(Comparator.comparing(Product::getAmount))
                .collect(Collectors.toList());

        List<Product> stockSortList = testList.stream()
                .sorted(Comparator.comparing(Product::getStockNum).reversed())
                .collect(Collectors.toList());
        System.out.println("amountSortList :" +amountSortList.toString());
        System.out.println("stockSortList :" +stockSortList.toString());
    }

看到排序效果是很OK的 : 

接下来我们来看看 浅拷贝的问题场景 :

我们对初始数据 list 进行动手脚,看下是否会影响 list.stream() 出来的新的list

动手脚 ① ,我们进行新增、删除、清除 这些操作 :
 

这时候有没有一些看客在想, 是不是这就是深拷贝呢? 

对原数据操作,新出来的list没有被影响,这不就是深拷贝么?

继续看

动手脚 ②  我们修改 原数据里面的值 :

可以看到结果:

受影响了
 

到这,我们先不说原因和结论,继续看。

动手脚 ③ 我们修改 第一次list.stream() 出来的list里面的值 :
 

这时候,大家可以想下,有啥影响,下面的根据库存排序 用的是 testList 初始数据做排序的。

直接看下效果:

定论:

①list.stream 是浅拷贝

② list里面装对象, 无论是 add 、remove 、clear  都不会出现牵连影响

③ list里面装对象, 无论是针对初始list还是新的list, 做了set 编辑修改动作, 都会出现牵连影响

简述原由:

我用几幅图来说下 

图一

list 里面装对象,对象其实都是同一份引用地址,我就故意画成下面这样,希望大家能看清晰些

图二 

自己list针对引用product的内存地址引用,多少 与其他list没有关系

图三

无论你在哪个list,针对product做set操作,修改值, 那么这对象product内测引用地址,也就是相当于公共财产,大家都引用着, 所以哪里动了,用着的都是受害群体。

最后,如果为了避免以上场景出现,我们需要用到list的深拷贝,那么怎么去使用?

深拷贝

简单列举几样:
 

① 序列化 

示例:
 

List<Product> newList = JSON.parseArray(JSON.toJSONString(testList), Product.class);

 引用jar:

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.69</version>
        </dependency>

② 使用字节流重新生成

    public static <T> List<T> doCopy(List<T> src) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(src);

        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream in = new ObjectInputStream(byteIn);
        List<T> dest = (List<T>) in.readObject();
        return dest;
    }

额外需要将实体类实现序列化

public class Product implements Serializable

使用:

        List<Product> newList =doCopy(testList);

③ 用MapperFacade

引入jar:
 

        <dependency>
            <groupId>net.rakugakibox.spring.boot</groupId>
            <artifactId>orika-spring-boot-starter</artifactId>
            <version>1.9.0</version>
        </dependency>

使用:

    @Autowired
    private MapperFacade mapperFacade;



List<Product>  newList = mapperFacade.mapAsList(testList, Product.class);

④使用  MapStruct ,这个不单独列举了

⑤ 手写,循环,new对象,set赋值,再add,这个也不单独列举了

好了,该篇就到这,谢谢。

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

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

相关文章

Nacos服务注册成功,RestTemplate调用服务提供者时空指针异常(已解决)

发现问题并进行记录 目录 项目场景&#xff1a;问题描述原因分析解决 项目场景&#xff1a; RestTemplate也可以做服务调用(进行测试) 目的:解决该问题,不考虑其他远程调用方式(Fegin,Dubbo) 项目Pom文件 Spring Boot ----2.6.3 Spring Cloud------2021.0.1 Spring Cloud Al…

Elasticsearch介绍和安装

ELK简介 Elastic Stack核心产品包括Elasticsearch、Logstash、Kibana&#xff08;也称为ELK&#xff09;和Beats等等。能够安全可靠地获取任何来源、任何格式的数据&#xff0c;然后实时地对数据进行搜索、分析和可视化 Kibana是一个免费且开放的用户界面&#xff0c;能…

Apikit 自学日记:可以对 API 发评论

该功能仅供API研发管理企业版 您可以直接在API文档上发布评论&#xff0c;所有的沟通内容都会跟随API文档保留下来并且按照版本分类好&#xff0c;而不是零散地存在各种聊天工具中。 发表评论 在API详情页&#xff0c;点击 评论 按钮&#xff0c;在弹窗中可以输入评论信息并点…

FPGA实验一:层次法设计组合电路(加法器)

目录 一、实验目的 二、实验要求 三、实验代码 四、实验结果及分析 1、引脚锁定 2、仿真波形及分析 3、下载测试结果及分析 五、实验心得 一、实验目的 &#xff08;1&#xff09;掌握基本组合逻辑电路的 FPGA实现&#xff1b; &#xff08;2&#xff09;学习 Verilo…

使用安装器安装windows gcc— MinGW及让windows像Linux一样的MSYS

这里使用installer进行安装GCC&#xff0c;主要是installer安装其它依赖&#xff0c;如MSYS&#xff0c;autoconf,automake&#xff0c;libtool&#xff0c;vim,perl,mingw-developer-toolkit等&#xff0c;mingw下载地址&#xff0c;如图download链接的mingw-get-setup.exe文件…

高级端口扫描工具

高级端口扫描程序可查看哪些服务在哪个端口上运行、开放端口数量、连接的交换机&#xff0c;并帮助保护网络免受未经授权的访问。作为网络管理员&#xff0c;扫描网络中的开放端口、这些端口已连接到的交换机以及在其上运行的服务&#xff0c;并将已知服务与已识别的服务与高级…

迁移学习入门,新手该如何下手?

推荐迁移学习技术的实用入门图书:《自然语言处理迁移学习实战》 [加纳] 保罗阿祖雷&#xff08;Paul Azunre&#xff09; 著&#xff0c;李想&#xff0c;朱仲书&#xff0c;张世武 译 一本书带你读懂ChatGPT背后的技术&#xff0c;自然语言处理迁移学习&#xff0c;解锁机器学…

Xcode Build System

Xcode Build System iOS开发者都使用Xcode来开发、编译程序&#xff0c;但是我们真正了解xcode是怎样编译我们的程序到手机上的么&#xff0c;下面我们主要看看xcode的编译系统内容 一、Preprocessor 预处理&#xff1a;在此步骤中xcode会处理代码中的宏&#xff0c;将其展开…

19k字图文讲解Vision科研常用的系统环境配置和工具(附详细命令行)

猛码Memmat | 转载请注明来源 最近作者有了新设备,趁更新系统写一篇博客为小白讲解这一入门过程 目录 ArchLinux 安装指南(新手向)前言准备工作检查网络通过 SSH 远程连接(可选)硬盘分区格式化并挂载分区设置中国镜像源(推荐)安装系统系统初始化设置进阶设置设置交换空…

VScode中的插件

开启VScode中最简单的内部浏览器 - 可以访问外网 - Browser Preview 插件安装&#xff1a; 插件使用&#xff1a;由下角 - 状态栏 - VS Browser按钮 live sass compiler-vscode插件将scss编译为css live sass compiler是VSCode扩展&#xff0c;可以实时地将SASS / SCSS文件…

基于Spring Boot的智慧社区系统设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; https://www.bilibili.com/video/BV1kF411R7Tp/?vd_sourced8d0eebf6c94c5aa49fe3f992c8887b0使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 后端&#xff1a;Java springboot框架 myba…

Django搭建图书管理系统01

Django框架 Django是一个使用Python编写的开源Web应用程序框架。它采用了MVC&#xff08;Model-View-Controller&#xff09;的软件设计模式&#xff0c;旨在简化开发复杂的Web应用程序。 以下是Django框架的一些主要特点&#xff1a; 强大的开发工具&#xff1a;Django提供了…

计算机毕业论文内容参考|基于Python的入侵检测系统的设计与实现

文章目录 导文摘要前言绪论课题背景国内外现状与趋势课题内容相关技术与方法介绍系统分析系统设计系统实现系统测试总结与展望导文 计算机毕业论文内容参考|基于Python的入侵检测系统的设计与实现 摘要 本文介绍了基于Python的入侵检测系统的设计与实现。首先,简要概述了入侵…

ubuntu中使用docker部署mysql

docker images&#xff1a;查看已有镜像docker pull mysql&#xff1a;拉取镜像docker ps -a&#xff1a;查看已有容器docker -o mysql8.0.33.tar&#xff08;保存镜像使用的名称&#xff09; mysql&#xff08;被保存的镜像&#xff09;&#xff1a;避免重复下载&#xff0c;可…

CMU 15-445 -- Tree Indexes - 05

CMU 15-445 -- Tree Indexes - 05 引言Table IndexB TreeB-Tree FamilyB TreeB Tree NodesB Tree OperationsIn Practice Clustered IndexesCompound IndexB Tree Design ChoicesNode SizeMerge ThresholdVariable Length KeysNon-unique IndexesIntra-node Search Optimizatio…

Nginx配置图片服务器

Nginx配置图片服务器 背景请求示例Nginx配置图片服务器问题存在 背景 在我们日常做项目的时候&#xff0c;我们有时候会经常碰到图片需要放到哪&#xff1f;有时候会用第三方的图片存储&#xff0c;比如腾讯云的COS&#xff0c;阿里云的OOS。当然有时候我们也是需要放到Linux的…

找不到 配置管理器。sql server 2008 r2 在win10下

win10 打开sqlserver2008r2的SQL Server 配置管理器 &#xff0c;通过开始程序中找不到“SQL Server 配置管理器”。去自己电脑上此目录找&#xff0c;“C:\Windows\SysWOW64\SQLServerManager10.msc”&#xff0c;直接运行此文件就可以调出“SQL Server 配置管理器”。 在win1…

docker环境下安装RabbitMQ3.8.2

一、下载指定版本镜像 [rootnginx ~]# docker pull rabbitmq:3.8.2-management 二、创建容器&#xff0c;并映射相关接口 [rootnginx ~]# docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369 -p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:3.8.2…

Spring Boot 中的 Seata 分布式事务

Spring Boot 中的 Seata 分布式事务 在分布式系统中&#xff0c;保证数据的一致性是一个非常重要的问题。传统的 ACID 事务模型虽然能够保证单个数据库的数据一致性&#xff0c;但是在分布式系统中却很难实现。因此&#xff0c;近年来出现了一些新的事务模型&#xff0c;其中 …

【QT】QIcon设置窗口小图标(12)

如何设置窗口小图标呢&#xff0c;很简单&#xff01; 导入库&#xff1a; from PyQt5.QtGui import QIcon ##导入库if __name__ __main__:app QApplication(sys.argv)MainWindow QMainWindow()ui xxx.Ui_MainWindow()ui.setupUi(MainWindow)app.setWindowIcon(QIcon(xxx…