谈谈知识的融会贯通:以“java中的迭代器失效问题”为例
提示
文中涉及知识点:
- Collection 、 Iterator
- Guava 中的 Lists.partition 方法
如果你对这两个知识点不了解,强烈建议阅读文中引用的参考文章。
场景一:以ArrayList为例
参考文章 java迭代器失效 和 Collection与Iterator的remove()方法区别与ConcurrentModificationException异常 ,可将迭代器和 Collection 的不同理解为:迭代器是基于 Collection 的一个视图,迭代器执行诸如 remove 和 add 之类的操作时,会首先在底层 Collection 上操作,最后将 expectedModCount 更新为新的 modCount ,而直接操作 Collection 则只会更新 modCount ,导致 fail-fast 机制生效。因此我们应在涉及到此类操作时尽可能只使用迭代器,可参考文章 Java:使用Iterator迭代器遍历集合数据 。
场景二:以Guava中的Lists.partition为例
参考文章 列表分片实现 和 Java 集合细节(三):subList 的缺陷 ,可知 Lists.partition 的底层实现就是 subList 方法,而 subList 函数返回仅仅只是一个视图,因此这里的 subList 其实和前面所述的迭代器在概念上是一样的(只是新的分片 List 的计数变量不叫 expectedModCount,而是和原 List 一样的 modCount,通过 this 区分),它们都是在原 List 的上层产生的视图,然后我们使用这个视图进行各种操作。因此,第二篇文章中所谓的 subList 缺陷其实不能叫做缺陷:我们在原 List 上通过 subList 获得其分片视图后,就不应该再操作原 List 了(类似于迭代器,我们获得一个 List 的迭代器后,应使用该迭代器进行各种操作,如前所述,此时针对原 List 的一些操作是危险的)。
当然,第二篇文章之所以将其称为“缺陷”也有原因:我们通常会认为获得的新分片 List 是新的 List ,这就是语言层面的理解了。
场景三:浅谈Guava中的集合类
其实,Guava中的多种集合如Maps、Lists均没有实现自定义的add操作。以Lists为例,当我们用Lists.transform或是Lists.partition函数返回新的集合时,都是Lists的内部类,这些内部类同样没有实现add方法,因此当我们视图在新的集合上进行add操作时,就会调用AbstractList的add方法,此方法会直接抛出UnsupportedOperationException。不过,我们仍旧可以在旧的集合中进行add操作,此时新集合也能看到刚刚add进去的元素,这是需要注意的。
总结
有时很多概念描述有很大不同,其实内部原理是相通甚至相同的,将这些概念融会贯通将大有裨益。
如果你了解 C++ 的话,可以参考 vector 容器的 insert 和 erase 方法,其实底层原理和 java 也是类似的。
扩展:多线程场景
注意,ArrayList并不是线程安全的,若不追求数据强一致性,可使用 CopyOnWriteArrayList 方法,可参考 聊聊并发-Java中的Copy-On-Write容器 和 JDK 5.0 中更灵活、更具可伸缩性的锁定机制 。
其他扩展文章
为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作
谈谈知识的融会贯通:以“java中的迭代器失效问题”为例的更多相关文章
- Java基础知识强化106:Java中 int 的各进制之间的转换
1.二.八.十.十六进制之间的转换 下面是示例代码,我们直接通过JDK工具库中的方法实现的,如下: public static Integer valueOf(String s, int radix ...
- Java基础知识强化101:Java 中的 String对象真的不可变吗 ?
1. 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...
- Java基础知识强化03:Java中的堆与栈
1.在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认识Stack和Heap,并通过这些原理认清Java中静态方法和静态属性的问题. 一般,JV ...
- Java基础知识强化10:Java中的中间缓存变量机制
1.对于自增运算++j与j++,由于加一的执行顺序不同,所以Java中有中间缓存变量来储存其单个表达式的值,而j的自增自减的结果依然保留在原来的变量储存区.因为本体是j的值,而单个表达式的值是中间产生 ...
- Java基础知识强化19:Java中switch分支语句
java中switch语句: 这里expression控制表达式的数据类型只能是byte.short.char.int四种整型类型和枚举类型,不能是boolean类型: Java7(1.7)改进了sw ...
- Java基础知识强化24:Java中异常
1.什么是异常 ? Java程序运行中,常常会遇到非正常的现象,这种情况称为运行错误.根据性质可以分为错误和异常.Java程序中(无论谁写的代码),所有抛出(throw)的异常都必须从Th ...
- Java基础知识强化22:Java中数据类型转换
数据类型转换: (1). 自动转换 低级变量可以直接转换为高级变量,这叫自动类型转换.比如: byte b: int b: long b: float b: double b: 上面的语句可 ...
- Java基础知识强化21:Java中length、length()、size()区别
1.java中的length属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了length这个属性.2.java中的length()方法是针对字符串String说的,如果想看这个 ...
- 第一篇 网站基础知识 第4章 Java中Socket的用法
第4章 Java中Socket的用法 4.1 普通Socket的用法 Java中的网络通信是通过Socket实现的,Socket分为ServetSocket和Socket两大类,ServetSocke ...
随机推荐
- LAMP安装教程
LAMP环境配置安装注意安装步骤及说明事项. Linux + apache+mysql+php 附件: 1. 访问ftp报错 解决: 关闭selinux vi /etc/selinux/config ...
- Centos6.5---samba文件共享服务配置(一)
Linux---------samba文件共享服务配置(一) samba是一个实现不同操作系统之间文件共享和打印机共享的一种SMB协议的免费软件. https://www.cnblogs.com/zo ...
- UICollectionView添加 HeaderView FooterView
UICollectionView显示HeaderView FooterView 不如UITableView那么容易,常用会有两种做法: 1.Xib或者Storyboard 在属性一栏中设置一下: 如图 ...
- VSCode插件开发全攻略(四)命令、菜单、快捷键
更多文章请戳VSCode插件开发全攻略系列目录导航. 命令 我们在前面HelloWord章节中已经提到了命令写法,这里再重温一下. context.subscriptions.push(vscode. ...
- Windows 10 IoT Serials 11 – 如何设置微软认知服务中EndPoint
1.问题描述 在UWP应用开发过程中,如果要使用微软认知服务,很多开发者会使用Microsoft.Oxford.Face.Microsoft.Oxford.Vision的NuGet包来完成.如果在vi ...
- 工具安装(mac)
1. iterm 2. nvm 3. node 4. git 5. VScode 6. postman 1.安装iterm2安装路径 https://www.iterm2.com/使用技巧https: ...
- 脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?
1.引言 本文接上篇<脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手>,继续脑残式的网络编程知识学习 ^_^. 套接字socket是大多数程序员都非常熟悉的概念,它是计算机 ...
- 7.数据库、Contentobserver
群组页是程序内部维护的一个数据库,其中一张表groups,用于存放创建的群组,还有一张表thread_group,用于关联群组和系统短信数据库中的会话. 数据库应该这样设计 MySqliteHelpe ...
- feign包名路径添加问题
1. feign包名路径添加问题 1.1. 问题 在SpringCloud中使用feign调用路径中,不能在类上直接添加@RequestMapping(value = "/hospital- ...
- socket 实现单一串口共享读写操作
前提:物理串口连接到PC上,通过串口号被PC唯一识别. 此时,物理串口通过该串口号仅能被单一线程或进程实例并占用,其他线程或进程不能再通过该串口号与物理串口通信.这个暂称为串口独占性. 解决思路:核心 ...