subList与原始List相互影响

在 Java 中,List#subList(int fromIndex, int toIndex) 方法返回的是原始列表的一个视图(view),而不是一个独立的副本。这意味着对 subList 的任何修改都会反映到原始列表中,反之亦然。这可能会导致意外的行为,尤其是在你期望 subList 是一个独立的列表时。

示例:

package org.example.a;import java.util.ArrayList;
import java.util.List;public class Demo {public static void main(String[] args) {List<Integer> integerList = new ArrayList<>();integerList.add(1);integerList.add(2);integerList.add(3);// 获取子列表List<Integer> subList = integerList.subList(0, 2);// 修改子列表中的元素subList.set(0, 10);// 修改原始列表中的元素integerList.set(1, 20);System.out.println("integerList: " + integerList);System.out.println("subList: " + subList);}
}

运行结果:

integerList: [10, 20, 3]

subList: [10, 20]

解释:

        修改 subList :当你调用 subList.set(0, 10) 时,实际上是在修改原始列表 integerList 的第一个元素,因此 integerList 的第一个元素变成了 10

        修改 integerList :当你调用 integerList.set(1, 20) 时,integerList 的第二个元素变成了 20,同时这个变化也会反映到 subList 中,因为 subList 只是 integerList 的一个视图。

源码

SubList 的工作原理:subList 方法

public List<E> subList(int fromIndex, int toIndex) {subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, 0, fromIndex, toIndex);
}

参数检查:首先调用 subListRangeCheck 方法确保索引范围有效。

返回 SubList 示例:然后创建并返回一个新的 SubList 对象,该对象持有对原始 ArrayList 的引用,并记录了子列表的起始和结束位置。

SubList 类

private class SubList extends AbstractList<E> implements RandomAccess {private final AbstractList<E> parent;private final int parentOffset;private final int offset;int size;SubList(AbstractList<E> parent,int offset, int fromIndex, int toIndex) {this.parent = parent;this.parentOffset = fromIndex;this.offset = offset + fromIndex;this.size = toIndex - fromIndex;this.modCount = ArrayList.this.modCount;}public void add(int index, E e) {rangeCheckForAdd(index);checkForComodification();parent.add(parentOffset + index, e);this.modCount = parent.modCount;this.size++;}
}

parent 字段:保存对原始 ArrayList 的引用。

parentOffset 和 offset 字段:记录子列表相对于原始列表的偏移量。

size 字段:表示子列表的大小。

add 方法:当向 SubList 添加元素时,实际上是通过 parent.add(parentOffset + index, e) 来操作原始列表。这意味着添加到 SubList 的元素会直接反映在原始列表中。

潜在问题

由于 SubList 实际上只是原始列表的一个视图,因此存在以下潜在问题:

        1. 相互影响:对 SubList 或原始列表的任何修改都会影响到对方,因为它们共享相同的底层数据结构。

        2. 内存泄漏:如果 SubList 被保留而原始列表很大,则会导致原始列表无法被垃圾回收,即使不再需要整个列表。这可能会导致内存溢出(OOM)问题,特别是在大量创建小 SubList 的情况下。

示例

private static List<List<Integer>> data = new ArrayList<>();private static void oom() {for (int i = 0; i < 1000; i++) {List<Integer> rawList = IntStream.rangeClosed(1, 100000).boxed().collect(Collectors.toList());data.add(rawList.subList(0, 1));}
}

虽然 data 看起来只保存了 1000 个具有 1 个元素的子列表,但实际上每个 SubList 都强引用了整个 rawList,导致 GC 无法回收这些大列表,最终可能导致内存溢出(OOM)。

解决方案

        为了确保 subList 和原始列表之间没有相互影响,可以创建一个新的 ArrayList 来包含 subList 的内容。这样做会创建一个独立的副本,从而避免上述问题。

package org.example.a;import java.util.ArrayList;
import java.util.List;public class Demo {public static void main(String[] args) {List<Integer> integerList = new ArrayList<>();integerList.add(1);integerList.add(2);integerList.add(3);// 创建新的 ArrayList 包含 subList 的内容List<Integer> subList = new ArrayList<>(integerList.subList(0, 2));// 修改子列表中的元素subList.set(0, 10);// 修改原始列表中的元素integerList.set(1, 20);System.out.println("integerList: " + integerList);System.out.println("subList: " + subList);}
}

运行结果:

integerList: [1, 20, 3]

subList: [10, 2]

解释:

        修改 subList :由于 subList 现在是一个独立的 ArrayList,对它的修改不会影响到原始列表 integerList

        修改 integerList :同样地,对 integerList 的修改也不会影响到 subList,因为它们现在是完全独立的。

总结

subList 是原始列表的一个视图:它不是独立的副本,而是原始列表的一部分。因此,任何对 subList 或原始列表的修改都会相互影响。

内存管理问题:由于 subList 强引用了原始列表,可能导致不必要的内存占用,甚至引发 内存溢出(OOM) 错误。

解决方案:如果你需要一个真正独立的子列表,应该使用 new ArrayList<>(list.subList(...)) 来创建一个新的 ArrayList 包含 subList 的内容。这将确保两个列表之间的操作不会相互影响,并且避免潜在的内存问题。

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

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

相关文章

pytest入门三:setup、teardown

https://zhuanlan.zhihu.com/p/623447031 function对应类外的函数&#xff0c;每个函数调用一次 import pytest def setup_module():print(开始 module)def teardown_module():print(结束 module)def setup_function():print(开始 function)def teardown_function():print(结…

React+Antd修改Table组件滚动条样式

版本 Antd 5.x.x React 18.x.x Tsx <TabledataSource{SocrePaMing.length > 0 ? SocrePaMing : []}columns{tableScoreColumns}rowKey"attribute"pagination{false}className"custom-table"scroll{{ y: 400 }} /> Css .ant-table-body …

一、使用 mdadm 工具在 Ubuntu 上创建 RAID 1(镜像)

在 Ubuntu 上创建 RAID 1&#xff08;镜像&#xff09;可以使用 mdadm 工具。以下是详细的步骤&#xff0c;包括安装必要的工具、创建 RAID 阵列、格式化并挂载 RAID 设备。 步骤一&#xff1a;安装 mdadm 首先确保你已经安装了 mdadm 包&#xff0c;这是管理软件 RAID 所需的…

webstorm开发uniapp(从安装到项目运行)

1、下载uniapp插件 下载连接&#xff1a;Uniapp Tool - IntelliJ IDEs Plugin | Marketplace &#xff08;结合自己的webstorm版本下载&#xff0c;不然解析不了&#xff09; 将下载到的zip文件防在webstorm安装路径下&#xff0c;本文的地址为&#xff1a; 2、安装uniapp插…

Tomcat的下载和使用,配置控制台输出中文日志

目录 1. 简介2. 下载3. 使用3.1 文件夹展示3.1.1 控制台输出乱码 3.2 访问localhost:80803.3 访问静态资源 4. 总结 1. 简介 Tomcat&#xff0c;全称为Apache Tomcat&#xff0c;是一个开源的Web应用服务器和Servlet容器&#xff0c;由Apache软件基金会的Jakarta项目开发。它实…

低功耗视频监控丨4G无线太阳能监控系统在林业场景中如何发挥作用?

在林业领域&#xff0c;4G无线太阳能监控系统的引入标志着向绿色、智能管理迈出的重要一步。视频监控太阳能供电通过集成太阳能供电、4G无线通信、视频监控和物联网技术&#xff0c;为林业监控提供了一个绿色、智能、高效的解决方案。它不仅能够实现对森林资源的实时监控&#…

硬链接方式重建mysql大表

硬链接方式重建mysql大表 操作步骤 选择数据库 select datadir; 进入数据文件目录 cd /data/mysql/mydata/testdb 创建硬连接 ln test_trans_msg_xx.ibd test_service_trans_msg_xx.ibd.bak ll test_trans_msg_xx* 进库删除表 DROP TABLE test_trans_msg_xx; 重建表 CREATE T…

dolphinscheduler服务RPC框架源码解析(二)RPC核心注解@RpcService和@RpcMethod设计实现

1.工程目录 从3.2.1版本之后这个dolphinscheduler中的RPC框架工程就从原来的dolphinscheduler-remote工程重构到了dolphinscheduler-extract工程。 dolphinscheduler 父项目 dolphinscheduler-extract RPC服务项目 dolphinscheduler-extract-alert 监控告警服务RPC接口定义、…

解析 .proto 文件

我这里仅仅是介绍了proto这个库解析.proto文件后的参数 我也有个小demo对解析的数据进行使用&#xff0c;具体代码可以看这know-bay 下面解析不是很全面&#xff0c;但是对于现在我的来说是够用的&#xff0c;关于更加详细和全的&#xff0c;看以后是否有机会补充了 假设 .prot…

grpc的负载均衡

grpc的负载均衡分为client-side load balance和server-side load balance。 所谓的“客户端负载均衡”是指主调方调用被调方的时候&#xff0c;在grpc.DialContext里需要指定grpc.WithDefaultServiceConfig&#xff0c;这个DefaultServiceConfig默认是用pick-first策略。也支持…

太速科技-622-基于ADRV9002 +ZYNQ7020 的软件无线电 SDR(升级AD9361)

基于ADRV9002 ZYNQ7020 的软件无线电 SDR&#xff08;升级AD9361&#xff09; 一、板卡概述 板卡由ADI ADRV9002Xilinx XC7Z020-CLG484芯片设计的整板&#xff0c;包含双路射频输入输出通道&#xff0c;支持千兆网络&#xff0c;RS232&#xff0c;触摸屏等接口&#xff…

如何计算kv cache的缓存大小

符号定义 首先&#xff0c;定义一些符号&#xff1a; ( B )&#xff1a;批大小&#xff08;Batch Size&#xff09; ( L )&#xff1a;序列长度&#xff08;Sequence Length&#xff09; ( N )&#xff1a;Transformer 层数&#xff08;Number of Transformer Layers&#xf…

SpringBoot 手动实现动态切换数据源 DynamicSource (上)

大家好&#xff0c;我是此林。 在实际开发中&#xff0c;经常可能遇到在一个SpringBoot Web应用中需要访问多个数据源的情况。 下面来介绍一下多数据源的使用场景、底层原理和手动实现。 一、 多数据源经典使用场景 场景一&#xff1a;业务复杂&#xff0c;数据量过大 1. 业务…

SQLServer定时备份到其它服务器上

环境 Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) SQL Server Management Studio 15.0.18384.0 SQL Server 管理对象 (SMO) 16.100.46367.54 Microsoft .NET Framework 4.0.30319.42000 本地操作系统&#xff08;SQLServer环境&#xff09; Windows 11 远程操作系统…

PaddleOCR模型ch_PP-OCRv3文本检测模型研究(二)颈部网络

上节研究了PaddleOCR文本检测v3模型的骨干网&#xff0c;本文接着研究其颈部网络。 文章目录 研究起点残注层颈部网络代码实验小结 研究起点 摘取开源yml配置文件&#xff0c;摘取网络架构Architecture中颈部网络的配置如下 Neck:name: RSEFPNout_channels: 96shortcut: True可…

IEEE T-RO 软体机器人手指状态估计实现两栖触觉传感

摘要&#xff1a;南方科技大学戴建生院士、林间院士、万芳老师、宋超阳老师团队近期在IEEE T-RO上发表了关于软体机器人手指在两栖环境中本体感知方法的论文。 近日&#xff0c;南方科技大学戴建生院士、林间院士、万芳老师、宋超阳老师团队在机器人顶刊IEEE T-RO上以《Propri…

Java 环境变量配置全解析

一、Java 环境变量配置的重要性 程序运行基础 确保 Java 应用能够在操作系统中被正确识别和启动&#xff0c;否则将无法执行任何 Java 代码。为 Java 运行时环境&#xff08;JRE&#xff09;提供必要的路径信息&#xff0c;使其能找到所需的类库和资源。使得系统可以定位到 Jav…

AutoMQ x Iceberg SG Meetup: Table Topic 新特性统一流与分析首次公开

活动介绍 Apache Iceberg 已经成为数据湖表格式的事实标准&#xff0c;为存储在S3上的数据提供了统一的格式。随着 AWS 在 2024 年的 re:invent 大会上宣布支持 Iceberg Table 的 S3 Table 新特性&#xff0c;Iceberg 再一次受到全球开发者的关注和讨论。AutoMQ 是基于云优先理…

java-多线程的创造方式(自用笔记)

方式一&#xff1a;继承父类thread 1、定义一个子类&#xff0c;继承父类thread 2、重写父类的run方法 3、创建线程类的“对象” 4、启动线程 package week14;public class ThreadDemo {public static void main(String[] args) {//3、创建线程类的“对象”Thread t1 new…

【CSS in Depth 2 精译_071】11.4 思考字体颜色的对比效果 + 11.5 本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 11 章 颜色与对比】 ✔️ 11.1 通过对比进行交流 11.1.1 模式的建立11.1.2 还原设计稿 11.2 颜色的定义 11.2.1 色域与色彩空间11.2.2 CSS 颜色表示法 11.2.2.1 RGB…