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可以通过索引快速访问数据。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值