-
for
,forEach
,Iterator
在遍历上的效率区别
forEach
在遍历Obejct时编译后的源码是Iterator
,forEach
在遍历基本类型时编译后的源码是for循环。
遍历ArrayList
的时候forEach
,Iterator
差不多, for比这两个快一些。遍历LinkedList
的时候速度:forEach
,Iterator
>>for
。 -
AbstractList类有一个modCount字段,每次表结构发生修改时+1,用来确保简单的线程安全,迭代器在遍历时如果发现modCount发生修改时抛出
ConcurrentModificationException
异常。
![](https://img-blog.csdnimg.cn/direct/f0aff43a6ab74ec690ddaee2d0f2b3ce.png)
ArrayList
-
ArrayList
集成AbastractList
并实现RandomAcess
、Serializable
和Cloneable
三个接口。 -
默认容量为10,最大容量
Integer.MAX_VALUE
- 8。 -
数组存储元素,并不进行序列化。通过将 elementData 字段标记为 transient,在序列化过程中,该字段将被忽略,只序列化 ArrayList 对象中的元素和其他必要的状态信息。在反序列化时,ArrayList 对象会重新创建一个默认大小的数组,并将反序列化的元素放入该数组中。
transient Object[] elementData; // non-private to simplify nested class access
- 每次需要扩容时增加到1.5倍,
- - - - - - - - - - - - - - - - - - - - - - - - - - -
触发扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
- - - - - - - - - - - - - - - - - - - - - - - - - - -
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
扩容时
使用Arrays.copyOf(),和addAll
以及remove
等时会使用 System.arrayCopy。Arrays.copyOf()底层由System.arrayCopy实现,区别在于System.arrayCopy是从源数组向目标数组拷贝,没有返回值。Arrays.copyOf()创建新数组对象并拷贝。二者的都是浅拷贝
。
LinkedList
![](https://img-blog.csdnimg.cn/direct/000a5bd01a8f4117b6d88112c47b5b67.png)
Vector
![](https://img-blog.csdnimg.cn/direct/864c27fa7e5e421da9ec54ae0666813d.png)
Vector极少使用,如今为了线程安全通常会用copyOnWriteArrayList。
![](https://img-blog.csdnimg.cn/direct/1d1ad8ac4476442ea31d9e619a32e526.png)
-
COW意思就是大家共同去访问一个资源,如果有人想要去修改这个资源的时候,就需要复制一个副本,去修改这个副本,完成后再替换。避免影响读。
-
COW两个主要的属性
独占锁ReentrantLock,
多线程运行的情况下,只有一个线程会获得这个锁,只有释放锁后其他线程才能获得。
final transient ReentrantLock lock = new ReentrantLock();
存放数据的数组,关键是被volatile修饰了,被volatile修饰,
就保证了可见性,也就是一个线程修改后,其他线程立即可见。
private transient volatile Object[] array;
- 添加操作(修改删除类似)
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 获取原来的数组
Object[] elements = getArray();
// 原来数组的长度
int len = elements.length;
// 创建一个长度+1的新数组,并将原来数组的元素复制给新数组
Object[] newElements = Arrays.copyOf(elements, len + 1);
// 元素放在新数组末尾
newElements[len] = e;
// array指向新数组
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
Stack
![](https://img-blog.csdnimg.cn/direct/9c2c9322187b4138990904d8e166ae03.png)
- stack继承vector,四个常用操作push pop peek search 都加了syncronized(push使用addElement完成)。