ArrayList

ArrayList继承自AbstractList抽象类,实现了RandomAccess, Cloneable, java.io.Serializable接口,其中RandomAccess是一个标志接口,代表可以支持快速随机访问,实现该接口的类使用for循环比使用迭代器要快,LinkedList并未实现该接口,它用迭代器进行遍历要比ArrayList用迭代器要快。可以用instanceof确定某obj是否实现RandomAccess。Cloneable:标志接口,表示可被克隆;java.io.Serializable可序列化标志接口。(克隆和序列化还能继续研究 。。。)


ArrayList是动态的、长度可变的,但底层由长度不可变的数组实现,默认数组大小为10,可以用ArrayList(int lenth)初始化数组长度,也可以使用ensureCapacity(int minCapacity)来预估数据数量而提前扩容(用此方法扩容时ArrayList不能为空数组)。

在进行扩容时多次使用Arrays.copyOf(obj [],newObj [])方法,扩容大小由内部方法newCapacity(int minCapacity)确定:

/**
* Returns a capacity at least as large as the given minimum capacity.返回至少与给定最小容量相同的容量
* Returns the current capacity increased by 50% if that suffices.如果满足,则返回当前容量增加50%
* Will not return a capacity greater than MAX_ARRAY_SIZE unless
* the given minimum capacity is greater than MAX_ARRAY_SIZE.
*除非给定的最小容量大于MAX_ARRAY_SIZE,否则不会返回大于MAX_ARRAY_SIZE的容量。
* @param minCapacity the desired minimum capacity
* @throws OutOfMemoryError if minCapacity is less than zero
*/
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//原长度
int newCapacity = oldCapacity + (oldCapacity >> 1);//原长度1.5倍
if (newCapacity - minCapacity <= 0) {//如果给定长度大于1.5倍
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math.max(DEFAULT_CAPACITY, minCapacity);//为空则返回给定和默认中大的
if (minCapacity < 0) // overflow不能给负数
throw new OutOfMemoryError();
return minCapacity;//否则就返回给定值
}
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);//这里,MAX_ARRAY_SIZE为Integer.MAX_VALUE-8,因为部分虚拟机会存储head code(头部信息?),所以直接给Integer.MAX_VALUE会报错:数组大小超出VM限制。但它还是会把这8个位置给你233333
}

说完扩容,说缩容,正常情况下开辟过的容量并不会减少,不使用了会赋null(比如clear()方法,以及内部的protected void removeRange()),但这样会造成浪费,因此可以使用trimToSize()方法把其中的数组大小修改为元素数量(trim:修剪)。

其中add、remove方法使用System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length)来创建新的数组,从而表现出长度可变的特性。//这么做代表数组中间不会有null值,但是数组尾部未使用的会有null值。

removeAll(c),可以删除和c相同的元素,也就是求与c的差集;

retainAll(c),可以保留和c相同的元素,也就是求与c的交集。这两个方法都调用了期内部方法`batchRemove方法:

boolean batchRemove(Collection<?> c, boolean complement,
final int from, final int end) {
Objects.requireNonNull(c);//c中不能有null
final Object[] es = elementData;//获取原数组
int r;//声明遍历标志位
// Optimize for initial run of survivors
//优化幸存者的初始运行,也就是处理需要保留的元素
for (r = from;; r++) {
if (r == end)//removeAll与retainAll方法调用时传参from为0,end为数组大小size,这里判断是否需要执行删除操作
return false;//false代表没有元素删除
if (c.contains(es[r]) != complement)
break;//代表需要删除元素
}
int w = r++;//声明保留标志位,初始化为第一个要删除的元素,同时r+1继续遍历
try {
for (Object e; r < end; r++)
if (c.contains(e = es[r]) == complement)
es[w++] = e;//这里执行的不是删除,而是将后面需要保留的元素覆盖掉第一个需要删除的元素,相当于把需要保留的元素向前移动了
} catch (Throwable ex) {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
//保留与AbstractCollection的行为兼容性,即使c.contains()抛出也是如此。
System.arraycopy(es, r, es, w, end - r);
w += end - r;
throw ex;
} finally {
modCount += end - w;//修改(删除)的次数
shiftTailOverGap(es, w, end);//拷贝需要保留的元素,同时将后面移动过后的元素赋null
}
return true;//代表修改(删除)了元素
}

该方法还是比较精妙的。

至于迭代器了,恕笔者学识尚浅,就不发表拙见了//待更新。。。


疑点:其中两个私有的io方法,这俩玩意有什么用?私有不说,光见它声明没见它调用啊//待更新。。。

/**
* Saves the state of the {@code ArrayList} instance to a stream
* (that is, serializes it).
*
* @param s the stream
* @throws java.io.IOException if an I/O error occurs
* @serialData The length of the array backing the {@code ArrayList}
* instance is emitted (int), followed by all of its elements
* (each an {@code Object}) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // Write out size as capacity for behavioral compatibility with clone()
s.writeInt(size); // Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
} if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
} /**
* Reconstitutes the {@code ArrayList} instance from a stream (that is,
* deserializes it).
* @param s the stream
* @throws ClassNotFoundException if the class of a serialized object
* could not be found
* @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException { // Read in size, and any hidden stuff
s.defaultReadObject(); // Read in capacity
s.readInt(); // ignored if (size > 0) {
// like clone(), allocate array based upon size not capacity
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
Object[] elements = new Object[size]; // Read in all elements in the proper order.
for (int i = 0; i < size; i++) {
elements[i] = s.readObject();
} elementData = elements;
} else if (size == 0) {
elementData = EMPTY_ELEMENTDATA;
} else {
throw new java.io.InvalidObjectException("Invalid size: " + size);
}
}

ArrayList源码阅读笔记的更多相关文章

  1. ArrayList源码阅读笔记(1.8)

    目录 ArrayList类的注解阅读 ArrayList类的定义 属性的定义 ArrayList构造器 核心方法 普通方法 迭代器(iterator&ListIterator)实现 最后声明 ...

  2. ArrayList源码阅读笔记(基于JDk1.8)

    关键常量: private static final int DEFAULT_CAPACITY = 10; 当没有其他参数影响数组大小时的默认数组大小 private static final Obj ...

  3. jdk源码阅读笔记-LinkedHashMap

    Map是Java collection framework 中重要的组成部分,特别是HashMap是在我们在日常的开发的过程中使用的最多的一个集合.但是遗憾的是,存放在HashMap中元素都是无序的, ...

  4. CopyOnWriteArrayList源码阅读笔记

    简介 ArrayList是开发中使用比较多的集合,它不是线程安全的,CopyOnWriteArrayList就是线程安全版本的ArrayList.CopyOnWriteArrayList同样是通过数组 ...

  5. Mina源码阅读笔记(四)—Mina的连接IoConnector2

    接着Mina源码阅读笔记(四)-Mina的连接IoConnector1,,我们继续: AbstractIoAcceptor: 001 package org.apache.mina.core.rewr ...

  6. HashMap源码阅读笔记

    HashMap源码阅读笔记 本文在此博客的内容上进行了部分修改,旨在加深笔者对HashMap的理解,暂不讨论红黑树相关逻辑 概述   HashMap作为经常使用到的类,大多时候都是只知道大概原理,比如 ...

  7. java8 ArrayList源码阅读

    转载自 java8 ArrayList源码阅读 本文基于jdk1.8 JavaCollection库中有三类:List,Queue,Set 其中List,有三个子实现类:ArrayList,Vecto ...

  8. CI框架源码阅读笔记5 基准测试 BenchMark.php

    上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功 ...

  9. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...

随机推荐

  1. POJ - 1847 Tram(dijkstra)

    题意:有向图有N个点,当电车进入交叉口(某点)时,它只能在开关指向的方向离开. 如果驾驶员想要采取其他方式,他/她必须手动更换开关.当驾驶员从路口A驶向路口B时,他/她尝试选择将他/她不得不手动更换开 ...

  2. BGR to RGB排列

    BGR to RGB排列 2012年09月27日 13:59:48 雷电羊 阅读数:4759   https://blog.csdn.net/cjsycyl/article/details/80247 ...

  3. git杂碎汇总

    1. .gitignore文件使用 1.如果不想某类文件(编译后.配置等文件)加入到git版本管理,可以在这个文件中配置规则,进行过滤筛选: 2.配置规则 以斜杠"/"表示目录:e ...

  4. 027、MySQL字符串替换函数,文本替换函数,字符串填充函数

    #文本填充 ,'); #ABC12121212121212121 #文本替换 SELECT REPLACE('田攀520','攀','ABC'); #田ABC520 不忘初心,如果您认为这篇文章有价值 ...

  5. oracle job不运行,定位问题

    一. job的运行频率设置 1.每天固定时间运行,比如早上8:10分钟:Trunc(Sysdate+1) + (8*60+10)/24*60 2.Toad中提供的: 每天:trunc(sysdate+ ...

  6. 《分布式消息中间件实践》P153

    问题:我直接把作者的源码拷贝下来(包括xml,resource等,作者应该使用的是Eclipse,我复制到IDEA上),依赖加上.执行P153的步骤,报错如下: Exception in thread ...

  7. python --- 日志模块 logging

    1.日志的使用 import logging class CommonLog(object): def _common_log(self,level,message): # 设定收集器,再设定收集的级 ...

  8. Spring Aop 原理分析

    @EnableAspectJAutoProxy Aop功能开启注解 为容器中导入 @Import(AspectJAutoProxyRegistrar.class)组件,在其重写方法中为 ioc容器 注 ...

  9. Laravel框架的学习

    用xampp环境 1.Composer的安装 http://www.phpcomposer.com/ 下载Composer的安装exe php.ini中extension_dir.browscap路径 ...

  10. 云时代架构阅读笔记一——Java性能优化(一)

    Java语言学习了这么长时间之后,自己对于Java编程的一些细节还是稍微有点总结,正好根据云时代架构中<Java高级开发必会的50个性能优化的细节(珍藏版)>来叙述一些我和里面的点比较相符 ...