Java中List的subList()方法及使用注意事项

article/2025/10/21 20:15:31
List<Object> list = new Arraylist<>();List<Object> subList = list.subList(0, 5);

其中subList(0, 5)取得的是下标为0到4的元素,不包含下标为5的元素.

java.util.List中的subList方法返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

List<E> subList(int fromIndex, int toIndex);

fromIndex - subList 的低端(包括)
toIndex - subList 的高端(不包括)

此方法省去了显式范围操作(此操作通常针对数组存在)。通过传递 subList 视图而非整个列表,期望列表的任何操作可用作范围操作。例如,下面的语句从列表中移除了元素的范围:

list.subList(from, to).clear();

下面通过代码来理解subList方法的使用

 List<String> parentList = new ArrayList<String>();for(int i = 0; i < 5; i++){parentList.add(String.valueOf(i));}List<String> subList = parentList.subList(1, 3);for(String s : subList){System.out.println(s);//output: 1, 2}subList.clear();System.out.println(parentList.size());//output: 3List<String> subList = parentList.subList(1, 3);在subList集合中的元素{1,2}中的第0的位置设置为new 1,即把1设置成了new 1subList.set(0, "new 1"); for(String s : parentList){System.out.println(s);//output: 0, new 1, 2, 3, 4}subList.add(String.valueOf(2.5));for(String s : parentList){System.out.println(s);//output:0, 1, 2, 2.5, 3, 4}//如果你在调用了sublist返回了子list之后,如果修改了原list的大小,那么之前产生的子list将会失效,变得不可使用。报 java.util.ConcurrentModificationExceptionparentList.add("undefine");for(String s : subList){System.out.println(s);}subList.get(0);

注意事项

ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException 异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.

说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、 删除均会产生 ConcurrentModificationException 异常。

List<Book> books = new ArrayList<>();Book book1 = new Book(1,"语文");books.add(book1);Book book2 = new Book(2,"数学");books.add(book2);Book book3 = new Book(1,"英语");books.add(book3);Book book4 = new Book(1,"网络安全");books.add(book4);Book book5 = new Book(1,"C语言程序设计");books.add(book5);System.out.println("原来的list:"+books.toString());List<Book> subList = books.subList(0, 1);for(int i=0;i<subList.size();i++){subList.get(i).setBookName(subList.get(i).getBookName()+"-updated");}System.out.println("修改后list:"+books.toString());

img


removeRange(int, int);这个方法AbstractList并没有暴露出来,我们应该如何得到一个截短的list?

1 如何得到一个list某个范围的子集sublist

首先想到sublist(int, int)方法
注意此方法参数左闭右开。
测试如下

1.1 修改sublist会影响原来的list

LinkedList<String> ll = new LinkedList<>();
ll.add("a");
ll.add("b");
ll.add("c");
List<String> l2 =  ll.subList(1, 2);//[)
l2.add("new");
System.out.println(ll);
System.out.println(l2);

运行结果:

[a, b, new, c]
[b, new]

可见sublist是快照,sulist插入会影响原list

1.2 修改原list,则sublist的所有操作会报错

LinkedList<String> ll = new LinkedList<>();
ll.add("a");
ll.add("b");
ll.add("c");
List<String> l2 =  ll.subList(1, 2);//[)
ll.add("d");
System.out.println(ll);
System.out.println(l2);

Exception in thread “main” java.util.ConcurrentModificationException
at java.util.SubList.checkForComodification(AbstractList.java:769)

可见如果更改了原来的list,sublist的任何操作都会报错,包括get() size(),listIterator()等所有调用checkForComodification()的地方。

2 如何正确的截断一个List?

subList()返回的是List!是Sublist,而不是原来的类型。

2.1在java.util.AbstractList.subList(int fromIndex, int toIndex)的定义,返回的是java.util.SubList.SubLis:

 public List<E> subList(int fromIndex, int toIndex) {return (this instanceof RandomAccess ?new RandomAccessSubList<>(this, fromIndex, toIndex) :new SubList<>(this, fromIndex, toIndex));}声明:class SubList<E> extends AbstractList<E>{}

2.2 LinkedList并没有覆盖这个方法.ArryList自己覆盖了这个方法,返回的是java.util.ArrayList.SubList:

public List<E> subList(int fromIndex, int toIndex) {subListRangeCheck(fromIndex, toIndex, size);return new SubList(this, 0, fromIndex, toIndex);
}
声明:
private class SubList extends AbstractList<E> implements RandomAccess {}

看来ArryList处处体现出RandomAccess接口的特性——支持随机访问。

2.3 我们看一下java.util.AbstractList.clear()方法,这正是我们需要的,Sublist的clear就是这个方法

public void clear() {removeRange(0, size());
}

2.3.1 ArrayList的覆盖

public void clear() {modCount++;// clear to let GC do its workfor (int i = 0; i < size; i++)elementData[i] = null;size = 0;
}

2.3.2 LinkedList的覆盖

public void clear() {for (Node<E> x = first; x != null; ) {Node<E> next = x.next;x.item = null;x.next = null;x.prev = null;x = next;}first = last = null;size = 0;modCount++;
}

3 根据1和2

截短一个List的正确姿势:

list.subList(from, to).clear();

总之:
subList是返回一个镜像而不是新示例 用了 得保证原来的list不能更改。
之前的抛异常是因为更改了原来的list而要使用sublist的时候必然报异常。
clear的这个跟这个问题说的是如何获得一个list的某一段顺便释放其他节点。
这个操作后原来的list会截取出来 类型不变。
而subList实际上返回的是java.util.Sublist或者java.util.ArrayList.Sublist。


http://chatgpt.dhexx.cn/article/0UAiOMpf.shtml

相关文章

Java 中 List.subList() 方法的使用陷阱

转载请注明本文出自 clevergump 的博客&#xff1a;http://blog.csdn.net/clevergump/article/details/51105235, 谢谢! 前言 本文原先发表在我的 iteye博客: http://clevergump.iteye.com/admin/blogs/2211979, 但由于在 iteye发表的这篇文章的某些渲染曾经出现过一些问题, 我…

【Java】List的subList方法

Java的容器类ArrayList很常用&#xff0c;旗下存在一个subList方法&#xff0c;是值得注意的。 subList方法仅能够取出此ArrayList的引用&#xff0c;即使其看起来&#xff0c;好像是取出一个ArrayList的子ArrayList。 其实不然&#xff0c;subList方法的返回值&#xff0c;只是…

Java中的subList方法

Java中的subList方法 今天看到了java中List中有个subList的方法&#xff0c;感觉很熟悉有没有&#xff1f;没错&#xff0c;在Stirng类中&#xff0c;也有个类似的方法&#xff1a;subString。 Stirng中的subString方法&#xff0c;官方解释是&#xff1a;返回字符串的子字符串…

Java中List集合的subList方法

目录 一、说明 二、测试 1、直接输出 2、向subList中添加元素再输出 3、 从subList中删除元素再输出 4、向list中添加元素再输出 5、从list中删除一个元素后再输出 ​ 6、向list中添加元素&#xff0c;输出list&#xff0c;然后将subList传入ArrayList生成新集合在输出…

你真的会用ArrayList的subList方法吗?

导语 在日常的开发中通常会遇到截取List的情况&#xff0c;而大多数会选择使用subList方法进行截取&#xff0c;但是好多人对这个方法的理解都只是停留在使用层面上&#xff1f;这篇文章会非常详细达到源码级别的讲解sublList方法&#xff0c;需要的朋友赶紧收藏起来吧。 关于…

Java SubList 类 Java subList方法 Java ArrayList$SubList 方法特点 SubList 用法

Java SubList 类 Java subList方法 Java ArrayList$SubList 方法特点 SubList 用法 一、概述 在java集合中&#xff0c;常用ArrayList类中&#xff0c;若需要对 list进行截取&#xff0c;可以使用subList方法&#xff0c;进行生成 SubList的内部类&#xff0c;那么 ArrayList 和…

使用ArrayList中的subList方法

集合是Java开发日常开发中经常会使用到的。在之前的一些文章中&#xff0c;我们介绍过一些关于使用集合类应该注意的事项&#xff0c;如《为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作》、《为什么阿里巴巴建议集合初始化时&#xff0c;指定集合容量大小》等…

sublist详解

接口中定义 List<E> subList(int fromIndex, int toIndex);1&#xff0c;该方法返回的是父list的一个视图&#xff0c;从fromIndex&#xff08;包含&#xff09;&#xff0c;到toIndex&#xff08;不包含&#xff09;。fromIndextoIndex 表示子list为空 2&#xff0c;父…

数据建模应用

数据建模应用 一、为什么要数据建模二、数据建模种类1、关系建模&#xff08;3NF&#xff09;2、维度建模 三、3NF数据建模1、范式介绍2、3NF建模实战 四、维度建模1、维度和指标的概念2、星型模型3、雪花模型4、星型与雪花模型对比5、维度建模测试案例 五、3NF建模与维度建模的…

分享大数据建模工具-大数据挖掘建模平台

大数据挖掘建模平台 是面向企业级用户的大数据挖掘建模平台。平台采用可视化操作方式&#xff0c;通过丰富内置算法&#xff0c;帮助用户快速、一站式地进行数据分析及挖掘建模&#xff0c;可应用于处理海量数据、高复杂性的数据挖掘任务&#xff0c;为其提供准确、高精度的计算…

大数据之数据模型

一、星型摸型 事实表是记录一个事实的&#xff0c;可以理解为订单表&#xff0c; 纬度表是提供更丰富信息的表&#xff0c;可以理解为商品明细表、订单明细表&#xff1b; 它是由一个事实表和一组维表组成&#xff0c;每个维表都有一个维作为主键&#xff0c;所有这些维的主键…

数据建模概述

数据建模&#xff08;data modeling&#xff0c;其实应该就是创建一个函数&#xff09;指的是对现实世界各类数据的抽象组织&#xff0c;确定数据库需管辖的范围、数据的组织形式等直至转化成现实的数据库。 将经过系统分析后抽象出来的概念模型转化为物理模型后&#xff0c;在…

大数据时代建模——图数据库建模

导读&#xff1a;云计算环境下&#xff0c;传统关系型数据库在海量数据存储方面存在瓶颈&#xff0c;对树形结构与半结构化数据的建模比较困难。本文介绍一种全新的建模方式——图数据库建模。应用图数据库模型更具扩展性、灵活性、高可靠性和高性能&#xff0c;能建立高细粒度…

大数据挖掘建模平台是怎样的?

大数据挖掘建模平台是可视化、一站式、高性能的数据挖掘与人工智能建模服务平台。面向企业级用户的大数据挖掘建模平台。平台采用可视化操作方式&#xff0c;通过丰富内置算法&#xff0c;帮助用户快速、一站式地进行数据分析及挖掘建模&#xff0c;可应用于处理海量数据、高复…

数据建模.

数据建模 什么是数据建模为什么要进行数据建模怎么进行数据建模 1. 为什么要进行数据建模&#xff1f; 提高 效率/性能&#xff1a; 计算机的的吞吐率&#xff0c;减少I/O的时间&#xff0c;提高用户使用数据的效率。开销&#xff1a;减少数据的冗余&#xff0c;从而节省存…

大数据数据建模

今天给大家分享一下 数据开发工作中数据建模的步骤&#xff0c; 第一步&#xff1a;选择模型或者自定义模型 这第一步需要我们基于业务问题&#xff0c;来决定我们需要选择哪种模型&#xff0c;目前市场中有很多模型可以供我们选择&#xff0c; 比如&#xff0c;如果要预测产…

数据建模

周三保(zhousbcn.ibm.com) IBM 软件部信息技术专家. 简介&#xff1a; 本文的主要内容不是介绍现有的比较流行的主要行业的一些数据模型&#xff0c;而是将笔者在数据仓库建设项目中的一些经验&#xff0c;在这里分享给大家。希望帮助大家在数据仓库项目建设中总结出一套能够合…

大数据分析及其建模利用

在数字经济时期&#xff0c;互联网、物联网、5G、大数据、智慧城市等各类模式的信息技术呈爆炸式增长&#xff0c;使得数据以令人难以设想的速度始终增长&#xff0c;企业运营的各个阶段都可以被记载下来&#xff0c;产品销售的各个环节也被记载下来&#xff0c;客户的生产行为…

浅谈大数据建模的主要技术:维度建模

文章目录 前言维度建模关键概念度量和环境事实和维度事实表维度表星形架构和雪花架构 维度建模一般过程1. 选取业务过程2. 定义粒度3. 确定维度4. 确定事实 前言 我们不管是基于 Hadoop 的数据仓库&#xff08;如 Hive &#xff09;&#xff0c;还是基于传统 MPP 架构的数据仓…

大数据建模五步法

from&#xff1a;https://www.sohu.com/a/198093510_783844 前一阵子&#xff0c;某网络公司发起了一个什么建模大赛&#xff0c;有个学员问我&#xff0c;数据建模怎么搞&#xff1f; 为了满足他的好学精神&#xff0c;我决定写这一篇文章&#xff0c;来描述一下数据分析必须…