当前位置:首页 > 科技  > 软件

Java|List.subList 踩坑小记

来源: 责编: 时间:2023-09-22 20:11:39 397观看
导读很久以前在使用 Java 的 List.subList 方法时踩过一个坑,当时记了一条待办,要写一写这事,今天完成它。我们先来看一段代码:// 初始化 list 为 { 1, 2, 3, 4, 5 }List<Integer> list = new ArrayList<>();for (int i = 1;

iOR28资讯网——每日最新资讯28at.com

很久以前在使用 Java 的 List.subList 方法时踩过一个坑,当时记了一条待办,要写一写这事,今天完成它。iOR28资讯网——每日最新资讯28at.com

我们先来看一段代码:iOR28资讯网——每日最新资讯28at.com

// 初始化 list 为 { 1, 2, 3, 4, 5 }List<Integer> list = new ArrayList<>();for (int i = 1; i <= 5; i++) {    list.add(i);}// 取前 3 个元素作为 subList,操作 subListList<Integer> subList = list.subList(0, 3);subList.add(6);System.out.println(list.size());

输出是 5 还是 6?iOR28资讯网——每日最新资讯28at.com

没踩过坑的我,会回答是 5,理由是:往一个 List 里加元素,关其它 List 什么事?iOR28资讯网——每日最新资讯28at.com

而掉过坑的我,口中直呼 666。iOR28资讯网——每日最新资讯28at.com

好了不绕弯子,我们直接看下 List.subList 方法的注释文档:iOR28资讯网——每日最新资讯28at.com

/** * Returns a view of the portion of this list between the specified * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.  (If * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is * empty.)  The returned list is backed by this list, so non-structural * changes in the returned list are reflected in this list, and vice-versa. * The returned list supports all of the optional list operations supported * by this list.<p> * * This method eliminates the need for explicit range operations (of * the sort that commonly exist for arrays).  Any operation that expects * a list can be used as a range operation by passing a subList view * instead of a whole list.  For example, the following idiom * removes a range of elements from a list: * <pre>{@code *      list.subList(from, to).clear(); * }</pre> * Similar idioms may be constructed for <tt>indexOf</tt> and * <tt>lastIndexOf</tt>, and all of the algorithms in the * <tt>Collections</tt> class can be applied to a subList.<p> * * The semantics of the list returned by this method become undefined if * the backing list (i.e., this list) is <i>structurally modified</i> in * any way other than via the returned list.  (Structural modifications are * those that change the size of this list, or otherwise perturb it in such * a fashion that iterations in progress may yield incorrect results.) * * @param fromIndex low endpoint (inclusive) of the subList * @param toIndex high endpoint (exclusive) of the subList * @return a view of the specified range within this list * @throws IndexOutOfBoundsException for an illegal endpoint index value *         (<tt>fromIndex < 0 || toIndex > size || *         fromIndex > toIndex</tt>) */List<E> subList(int fromIndex, int toIndex);

这里面有几个要点:iOR28资讯网——每日最新资讯28at.com

subList 返回的是原 List 的一个 视图,而不是一个新的 List,所以对 subList 的操作会反映到原 List 上,反之亦然;iOR28资讯网——每日最新资讯28at.com

如果原 List 在 subList 操作期间发生了结构修改,那么 subList 的行为就是未定义的(实际表现为抛异常)。iOR28资讯网——每日最新资讯28at.com

第一点好理解,看到「视图」这个词相信大家就都能理解了。我们甚至可以结合 ArrayList 里的 SubList 子类源码进一步看下:iOR28资讯网——每日最新资讯28at.com

private class SubList extends AbstractList<E> implements RandomAccess {    private final AbstractList<E> parent;    // ...    SubList(AbstractList<E> parent,            int offset, int fromIndex, int toIndex) {        this.parent = parent;        // ...        this.modCount = ArrayList.this.modCount;    }    public E set(int index, E e) {        // ...        checkForComodification();        // ...        ArrayList.this.elementData[offset + index] = e;        // ...    }    public E get(int index) {        // ...        checkForComodification();        return ArrayList.this.elementData(offset + index);    }    public void add(int index, E e) {        // ...        checkForComodification();        parent.add(parentOffset + index, e);        this.modCount = parent.modCount;        // ...    }    public E remove(int index) {        // ...        checkForComodification();        E result = parent.remove(parentOffset + index);        this.modCount = parent.modCount;        // ...    }    private void checkForComodification() {        if (ArrayList.this.modCount != this.modCount)            throw new ConcurrentModificationException();    }    // ...}

可以看到几乎所有的读写操作都是映射到 ArrayList.this、或者 parent(即原 List)上的,包括 size、add、remove、set、get、removeRange、addAll 等等。iOR28资讯网——每日最新资讯28at.com

第二点,我们在文首的示例代码里加上两句代码看现象:iOR28资讯网——每日最新资讯28at.com

list.add(0, 0);System.out.println(subList);

System.out.println 会抛出异常 java.util.ConcurrentModificationException。iOR28资讯网——每日最新资讯28at.com

我们还可以试下,在声明 subList 后,如果对原 List 进行元素增删操作,然后再读写 subList,基本都会抛出此异常。iOR28资讯网——每日最新资讯28at.com

因为 subList 里的所有读写操作里都调用了 checkForComodification(),这个方法里检验了 subList 和 List 的 modCount 字段值是否相等,如果不相等则抛出异常。iOR28资讯网——每日最新资讯28at.com

modCount 字段定义在 AbstractList 中,记录所属 List 发生 结构修改 的次数。结构修改 包括修改 List 大小(如 add、remove 等)、或者会使正在进行的迭代器操作出错的修改(如 sort、replaceAll 等)。iOR28资讯网——每日最新资讯28at.com

好了小结一下,这其实不算是坑,只是 不应该仅凭印象和猜测,就开始使用一个方法,至少花一分钟认真读完它的官方注释文档。iOR28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-11204-0.htmlJava|List.subList 踩坑小记

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 基于Python+Flask实现一个简易网页验证码登录系统案例

下一篇: 网络安全:渗透测试工程师必备的十种技能

标签:
  • 热门焦点
  • CSS单标签实现转转logo

    转转品牌升级后更新了全新的Logo,今天我们用纯CSS来实现转转的新Logo,为了有一定的挑战性,这里我们只使用一个标签实现,将最大化的使用CSS能力完成Logo的绘制与动画效果。新logo
  • 十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • 三分钟白话RocketMQ系列—— 如何发送消息

    我们知道RocketMQ主要分为消息 生产、存储(消息堆积)、消费 三大块领域。那接下来,我们白话一下,RocketMQ是如何发送消息的,揭秘消息生产全过程。注意,如果白话中不小心提到相关代
  • JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    来源:直播观察提起&ldquo;冯提莫&rdquo;这个名字,很多网友或许听过,但应该不记得她是哪位主播了。其实,作为曾经的&ldquo;斗鱼一姐&rdquo;,冯提莫在游戏直播的年代影响力不输于现
  • 2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
  • Counterpoint :OPPO双旗舰战略全面落地 高端产品销量增长22%

    2023年6月30日,全球行业分析机构Counterpoint Research发布的《中国智能手机高端市场白皮书》显示,中国智能手机品牌正在寻求高质量发展,中国高端智能
  • 华为举行春季智慧办公新品发布会 首次推出电子墨水屏平板

    北京时间2月27日晚,华为在巴塞罗那举行春季智慧办公新品发布会,在海外市场推出之前已经在中国市场上市的笔记本、平板、激光打印机等办公产品,并首次推出搭载
  • 世界人工智能大会国际日开幕式活动在世博展览馆开启

    30日上午,世界人工智能大会国际日开幕式活动在世博展览馆开启,聚集国际城市代表、重量级院士专家、国际创新企业代表,共同打造人工智能交流平台。上海市副市
Top