Java集合深入学习 - ArrayList源码解析-1基础(基于jdk1.8)
Java集合深入学习 - ArrayList源码解析-2序列化与迭代器(基于jdk1.8)
Java集合深入学习 - ArrayList源码解析-3子List与坑点(基于jdk1.8)
1.序列化操作
ArrayList在进行序列化操作的时候会遍历集合里的所有数据,然后对每个数据进行序列化。个人以为之所以对数据进行遍历之后分别序列化的原因是:避免数组大小与集合大小不一致时,将数组后面的null进行序列化。具体源码如下:
/**
* 序列化操作
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
int expectedModCount = modCount; //记录当前操作次数
s.defaultWriteObject(); //序列化 除transient修饰的其他数据 elementData数组就是被transient修饰的数据 //transient Object[] elementData;
s.writeInt(size); //序列化集合大小
//遍历数组中的数据,分别对每个数据进行序列化操作
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) { //若操作次数发生改变,说明在处理过程中集合被修改,则抛出ConcurrentModificationException异常
throw new ConcurrentModificationException();
}
}
2.迭代器
ArrayList类中包含有两个与迭代器相关的内部类Itr和ListItr, 其中参数方法如下:
其中Itr实现了集合的Iterator接口,其具体代码如下:
/**
* 定义一个内部类实现迭代器接口
* @author liu.suxing
*/
private class Itr implements Iterator<E> {
int cursor; // 当前迭代数据位置
int lastRet = -1; // 当前操作节点数据位置 无操作默认为-1
int expectedModCount = modCount; //记录修改次数
Itr() {}
/**
* 是否有下一个数据
*/
public boolean hasNext() {
return cursor != size; //判断当前数据是不是最后一个
}
/**
* 获取下一个数据 返回当前cursor位置数据
*/
@SuppressWarnings("unchecked")
public E next() {
checkForComodification(); //校验修改次数
int i = cursor; //当前数据位置
if (i >= size) //校验位置(size可能发生改变 列:被其他线程修改)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData; //获取集合中的数组
if (i >= elementData.length) //校验大小
throw new ConcurrentModificationException();
cursor = i + 1; //当前迭代数据位置+1
return (E) elementData[lastRet = i]; //返回当前位置数据
}
/**
* 删除当前迭代数据
*/
public void remove() {
if (lastRet < 0) //校验是否开始迭代数据
throw new IllegalStateException();
checkForComodification(); //校验修改次数
try {
ArrayList.this.remove(lastRet); //调用集合remove方法删除对应下标数据
cursor = lastRet; //修改当前迭代数据位置
lastRet = -1; //重置lastRet
expectedModCount = modCount; //重置expectedModCount
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
/**
* 迭代集合 根据传入的 函数式接口consumer进行对应的操作(消费)
*/
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer); //空指针校验
final int size = ArrayList.this.size; //获取当前数据大小
int i = cursor; //获取当前迭代位置
if (i >= size) { //校验
return;
}
final Object[] elementData = ArrayList.this.elementData; //获取当前集合中的数组
if (i >= elementData.length) { //位置校验
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) { //从cursor位置开始遍历数据
consumer.accept((E) elementData[i++]); //进行相关操作(消费)
}
cursor = i; //回到原来的迭代位置
lastRet = i - 1; //回到当前操作数据位置
checkForComodification(); //校验操作次数
}
/**
* 操作次数校验
*/
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
ListItr对Itr进行了一些封装,支持双向迭代,插入数据等操作,其具体代码如下:
/**
* List迭代器继承Itr
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) { //直接创建从指定位置开始迭代的迭代器
super();
cursor = index;
}
/**
* 是否有上一个数据
*/
public boolean hasPrevious() {
return cursor != 0; //返回当前位置是否为第一个
}
/**
* 获取下一个数据的位置
*/
public int nextIndex() {
return cursor;
}
/**
* 获取上一个数据的位置
*/
public int previousIndex() {
return cursor - 1;
}
/**
* 向前迭代 获取上一个迭代数据
*/
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification(); //校验操作次数
int i = cursor - 1; //获取当前操作数据位置
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i; //迭代位置 - 1
return (E) elementData[lastRet = i]; //返回当前数据 并给lastRet赋值
}
/**
* 修改当前迭代数据
*/
public void set(E e) {
if (lastRet < 0) //校验是否开始迭代数据
throw new IllegalStateException();
checkForComodification(); //校验操作次数
try {
ArrayList.this.set(lastRet, e); //调用ArrayList方法修改集合数据
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
/**
* 当前位置插入数据
*/
public void add(E e) {
checkForComodification(); //校验操作次数
try {
int i = cursor; //获取位置
ArrayList.this.add(i, e); //插入数据
cursor = i + 1; //修改迭代位置 到当前插入数据位置
lastRet = -1; //重置当前操作位置
expectedModCount = modCount;//重置操作次数
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
获取迭代器的3种方法,代码如下:
/**
* 获取一个从指定位置开始的List迭代器
* ListItr是ArrayList的一个内部类
*/
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size) //下标校验
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
/**
* 获取一个从第一个数据开始的List迭代器
* ListItr是ArrayList的一个内部类
*/
public ListIterator<E> listIterator() {
return new ListItr(0);
}
/**
* 获取一个迭代器(从第一个数据开始)
* Iterator是ArrayList的一个内部类
*/
public Iterator<E> iterator() {
return new Itr();
}
转载请标注https://blog.csdn.net/luo_mu_hpu/article/details/106120179