java集合类程序代码_java集合类源码学习二
我们查看Collection接口的hierarchy时候,可以看到AbstractCollection这样一个抽象类,它实现了Collection接口的部分方法,Collection集合系列的各个集合类都继承于该抽象类。我们来看看这个类:
public abstract class AbstractCollection implements Collection {
protected AbstractCollection() {
}
public abstract Iterator iterator();
public abstract int size();
public boolean isEmpty() {
return size() == 0;
}
public boolean contains(Object o) {
Iterator it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
@SuppressWarnings("unchecked")
public T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
Iterator it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) { // fewer elements than expected
if (a == r) {
r[i] = null; // null-terminate
} else if (a.length < i) {
return Arrays.copyOf(r, i);
} else {
System.arraycopy(r, 0, a, 0, i);
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T)it.next();
}
// more elements than expected
return it.hasNext() ? finishToArray(r, it) : r;
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
@SuppressWarnings("unchecked")
private static T[] finishToArray(T[] r, Iterator> it) {
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
if (i == cap) {
int newCap = cap + (cap >> 1) + 1;
// overflow-conscious code
if (newCap - MAX_ARRAY_SIZE > 0)
newCap = hugeCapacity(cap + 1);
r = Arrays.copyOf(r, newCap);
}
r[i++] = (T)it.next();
}
// trim if overallocated
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError
("Required array size too large");
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
Iterator it = iterator();
if (o==null) {
while (it.hasNext()) {
if (it.next()==null) {
it.remove();
return true;
}
}
} else {
while (it.hasNext()) {
if (o.equals(it.next())) {
it.remove();
return true;
}
}
}
return false;
}
public boolean containsAll(Collection> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
public boolean addAll(Collection extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
public boolean removeAll(Collection> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
public boolean retainAll(Collection> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
public String toString() {
Iterator it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
}
从它的代码里我们可以看到,它有一个最大长度,是Integer的最大值减去8,至于为什么减8,是因为有些JVM会在数组里保存几个关键字符。我们再看这个contains方法,我很好奇的是,既然参数是Object类型,那么就包括了null,为什么判断的时候还要把null单独拿出来,这个疑问不知哪个大佬能给我解释一下。
再看toArray的不带参方法,new了一个和size()方法表示的长度一样长的Object数组r,还弄了一个迭代器出来,然后用for来循环r数组的每一个下标,并在每一次循环中判断迭代器的hasNext()是否为false,如果为false则说明当前集合长度比r数组短,则用Array的copyOf()方法把r数组放到一个长度为i的数组里,这样就不浪费多余的空间了。最后判断如果hasNext()还为true,则说明当前集合长度比r数组长,就用finishToArray()方法返回一个Object数组。至于为什么比较过和size()的大小之后还有这种操作,上面注释有说明,是迭代的时候假如对元素有增删操作,会导致长度有变化。finishToArray(T[] r, Iterator> it)方法把数组r扩容之后往里面添加迭代器后续元素,可以看到hugeCapacity这个玩意,当数组长度超过Integer最大值减8的时候,就用Integer的最大值,这样数组的长度是不能超过2^31的,毕竟数组下标使用int数字表示的。带参的toArray方法差不多意思,是可以将集合转化成指定类型的数组。
add()方法会直接抛出异常,说明AbstractCollection是不允许添加元素的,那么一定是在具体实现类里实现的这个方法。至于其他的方法,看一下就明白了。
接着我们来看看public abstract class AbstractList extends AbstractCollection implements List,这是list的抽象类,继承自AbstractCollection,实现List接口的部分方法。源码就不贴了,现在重点来看一下内部类Itr,这是一个迭代器的实现类。里面定义了三个变量:游标cursor、最近一次调用返回的索引lastRet和期望得到的修改次数expectedModCount。里面实现了迭代器的三个方法,注意next()和remove()方法里都调用了这么一个方法checkForComodification(),这个用来比较expectedModCount和modCount,如果不同就抛出异常ConcurrentModificationException,这个意思是如果在迭代操作的时候,如果有用非迭代器的操作对集合做了修改,那么就会抛出异常。对于modCount,我们可以在AbstractList的子类中看到,每次对集合做了操作,modCount就会加一。
public static void main(String[] args) {
List list = new ArrayList();
list.add(11);
list.add(12);
list.add(13);
list.add(14);
list.add(15);
Iterator itr = list.iterator();
while(itr.hasNext()) {
if(itr.next() == 13) {
itr.remove();
}
}
System.out.println(list);
}
在迭代的时候用迭代器的remove操作就不会报错,如果在增强for循环中,用了ArrayList自带的remove,就会报异常了。下面的内部类ListItr是一个ListIterator的实现类,可以往前往后迭代,还有多了几个方法,代码都很简单。subList()截取一段子序列,支持往前往后截取。下面还有个SubList类,里面有个往后截取一段子序列的方法,其他的起始都是用的父类的方法。
java集合类程序代码_java集合类源码学习二相关推荐
- java集合类程序代码_Java集合类源代码分析二:ArrayList(1)
从java集合结构能够看出来ArrayList是属于Collection中的List范畴的.从源代码中是这样表示的, public classArrayList extends AbstractLis ...
- python程序代码解析_Python源码分析3 – 词法分析器PyTokenizer
Introduction 上次我们分析了Python中执行程序可分为5个步骤: Tokenizer进行词法分析,把源程序分解为Token Parser根据Token创建CST CST被转换为AST A ...
- JAVA 单商户商城系统 成熟源码 支持二开
三勾商城是开发友好的微信小程序商城,框架支持SAAS,支持发布 iOS + Android + 公众号 + H5 + 各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)等多个平台,不可多得的二开 ...
- 邮件 查看html源码,程序员跟着大师源码学习系列之2:查看网页和电子邮件的源码...
在最近的文章中有大量电子邮件相关的内容,已经有不少同学上手发送了很多的邮件到我的测试邮箱中.坦率地说,有不少同学发送的电子邮件格式都是错误的 ... 那么抛开各种深奥地理论,有没有一种方法可以看看 1 ...
- 使用base标签后图片无法加载_Spring 源码学习(二)-默认标签解析
`Spring` 解析默认标签~ 从上一篇笔记可以看出,在容器注册 bean 信息的时候,做了很多解析操作,而 xml 文件中包含了很多标签.属性,例如 bean . import 标签, meta ...
- ROS源码学习 二、线程池
2021SC@SDUSC 目录 1.写在前面 2.ROS线程池概述 3.ROS线程池模型 4.ROS线程池源码详解 5.总结 1.写在前面 ROS作为一个操作系统,其职责是协调具有不同功能的node之 ...
- yara 源码学习(二) 规则编译部分
yara规则的详细信息请参考: https://yara.readthedocs.io/en/stable/writingrules.html 根据官方文档,yara规则长这个样子: [1]:yara ...
- Box2d源码学习二内存管理之SOA的实现
本系列博客是由扭曲45原创,欢迎转载,转载时注明出处,http://blog.csdn.net/cg0206/article/details/8258166 SOA,全称small object al ...
- Golang源码学习(二)----Go源码学习基础
### 本文源码版本为 GO 1.17.8 Windows/amd64: ### 可能参与对比的版本:GO 1.16.2 Linux/amd64一.Golang的编译器究竟是如何工作的? (学习源码有 ...
最新文章
- 很多人都在埋怨没有遇到好的团队,但好的团队不可能凭空出现,一流的团队不能仅靠团队成员努力,作为Leader,要有可行的规划,并坚定地执行、时势地调整(转)...
- (转)access和SQL语句的区别
- Android之四大组件概念讲解
- 100行的python作品详解_不到 100 行 Python 代码徐峥变葛优
- REM重复制造MFBF功能
- “互联网+”未来发展
- 解决Ajax异步请求中传数组参数,后台无法接收问题
- python处理多个excel数据_python 数据分析基础 day8-pandas读写多个excel文件
- MJRefresh自定义刷新动画
- 浅谈c++纯虚函数的多态与数据隐藏
- OPPO手机完美安装Kingroot实现一键root
- yolov3训练实现火焰检测(pytorch)
- 如何搭建个人服务器(网站/游戏)?
- 用MyDiskTest检测存储卡真实容量(图)
- Ant Design Pro从零到一(认识AntD)
- 世界各国2015-2020GDP排名
- openlayers 地图上加图标_OpenLayers学习笔记中级篇(四、地图图标操作)
- [Tips]Ubuntu20.04域名解析失败或网速很慢
- 易飞9安装和授权视频
- 关于bitset中的 to_ulong()的解答
热门文章
- 分享一套主流框架源码资料,征服阿里 P7 面试必备!
- 阿里云1C2G虚拟机【99/年】羊毛党集合啦!
- 【并发编程】Atomic与CAS
- No rule to make target ‘../../libxxx_lib.so‘
- python 模板匹配多个物体
- python numpy数组和one-hot编码相互转换
- python 调用C++,传递int,char,char*,数组和多维数组
- yolo类检测算法解析——yolo v3
- 文本处理相关资料整理
- src.checkVector(2, CV_32F) == 4 dst.checkVector(2, CV_32F) ==4