Arraylist和Vector源码学习笔记

整体上这两个类都实现了List接口,继承AbstractList类。他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,可以按位置索引号取出某个元素。在看的时候,发现些疑点,找找原由,同时也去网上搜下,学习了以下几个关于Arraylist和Vector的几个小点:
1,同步性:

Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。

以上是网上一位老师的话,在Vector源码中一些操作方法都加了synchronized标识。

2,数据增长:

ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元。Vector默认增长为原来两倍,newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement ::oldCapacity),在容器构造时可以设置capacityIncrement 来决定增长的数量;而ArrayList的增长在文档中没有明确规定(从源代码看到的是增长为原来的1.5倍:newCapacity = oldCapacity + (oldCapacity >> 1);)。

3,vector提供了获取容器容量和元素数量的接口,而arraylist仅提供了获取元素数量的接口。

4,Arraylist中存储元素的数组elementData前加了transient标记。而加这个标记什么作用呢?elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量。假如现在实际有了5个元素,而elementData的大小可能是10,那么在序列化时只需要储存5个元素,数组中的最后五个元素是没有实际意义的,不需要储存。所以ArrayList的设计者将elementData设计为transient,然后在writeObject方法中手动将其序列化,并且只序列化了实际存储的那些元素,而不是整个数组

    以上是百度知道一位大神对elementData前加了transient标记作用的解释,膜拜中。

5,另外也新查了下另一个关于序列化和序列化的标记serialVersionUID的一些知识。
Java序列化是将一个对象编码成一个字节流,反序列化将字节流编码转换成一个对象。 序列化是Java中实现持久化存储的一种方法;为数据传输提供了线路级对象表示法。Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

6,modCount

这个modCount变量是AbstractList中的,ArrayList和Vector都继承了。每当对变量结构进行变化时modCount都会加1,这个作用主要是在对变量使用迭代器遍历的时候来检查列表中的元素是否发生结构性变化(列表元素数量发生改变)了。主要在多线程环境下需要使用,防止一个线程正在迭代遍历,另一个线程修改了这个列表的结构。

    本来看源码是为了学下编程规范。这个过程中发些一些疑点,就跟踪看,然后网上查下,其实发现有很多巧妙的东西。真是学习了,也感谢大神的智慧分享。

你可能感兴趣的:(java)