ArrayList学习笔记

Posted 等待戈多儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList学习笔记相关的知识,希望对你有一定的参考价值。

ArrayList的数据结构比较简单,但是其中也包含了一些好的设计思想。

ArrayList是用数组实现的,因为可以自动扩容(增加50%),所以ArrayList也可以理解为动态数组。

1.初始化

ArrayList的实现也是在不断改进的。在JDK1.7之后,ArrayList初始化的时候,elementData[]数组还是空的,并没有初始化长度为10的数组(困惑良久)。

private static final int DEFAULT_CAPACITY = 10;

//无参构造方法

 public ArrayList() 
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    

add(E e)时:

if (elementData == EMPTY_ELEMENTDATA) 
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        

if (minCapacity - elementData.length > 0)
            grow(minCapacity);

 if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

 elementData = Arrays.copyOf(elementData, newCapacity);

当add(E e)之后,newCapacity其实就是DEFAULT_CAPACITY(10)。这样做的好处就是new ArrayList<E>()时,并没有分配内存空间给elementData[]数组。


2.transient(瞬时)

private transient Object[] elementData;


这个关键字可能不常见,但是在JDK的源码中比较常见,HaspMap中EMPTY_TABLE[]也是transient修饰的。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

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


3.自动扩容(grow())

int newCapacity = oldCapacity + (oldCapacity >> 1);
elementData = Arrays.copyOf(elementData, newCapacity);

>>右移算术运算符,移动前加上符号位,负数加1,正数加0,然后移动

扩容造成的浪费可以调用trimToSize()方法:

if (size < elementData.length) 
            elementData = Arrays.copyOf(elementData, size);
        

trimToSize():应用程序可以使用此操作来最小化 ArrayList 实例的存储量。


4.非线程安全,可以调用Collections.synchronizedList(new ArrayList<>());实现。


List关注数据的索引列表。ArrayList可以通过索引快速访问数据。



以上是关于ArrayList学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

Java 集合学习笔记:ArrayList

JavaScript学习笔记四:基本概念

Java学习笔记--继承和多态(下)

ArrayList学习笔记

Java集合源码学习笔记LinkedList分析

Java 集合学习笔记:ArrayList