Java面试宝典——ArrayList构造函数剖析

构造函数:
无参构造在这里就不必再讲了。
下面讲讲连个有参构造函数:
1、传入初始容量值


这个构造函数的源码比较好懂,就是传入参数大于0,则初始化一个固定长度的Object数组给elementData;如果传入初始长度为0,则直接赋值Empty_ElEMENTDATA。否则,抛出异常。

2、传入集合Collection


这个方法就是我们经常用的,将一个list初始化给另一个list。如:List A = new ArrayList(); List B = new ArrayList(A);
这里第一行,执行elementData = c.toArray();
这里是将集合中的数组赋值给elementData,如果集合对象为空,则赋值一个空数组,如果不为空,判断数组是不是Object数组。如果不是,则将数组拷贝到重新定义的Object空数组中。

这里我们再探讨一下List的自动扩容的问题。
在我们上面讲到的第一个有参构造函数中,使用了EMPTY_ELEMENTDATA这个定义的空数组,我们上篇文章提到的无参构造函数初始化的时候使用的是DEFAULTCAPACITY_EMPTY_ELEMENTDATA。定义这两个不同的变量,其实就是为了区分一个东西。
在jdk1.8之前,ArrayList的无参初始化其实都是给定默认的长度,就是那个定义的DEFAULT_CAPACITY = 10.jdk1.8之后呢,就变成了DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这个在使用的时候如果容量不足的时候,扩容长度长度是随着添加元素的个数按需扩容;
而在使用EMPTY_ELEMENTDATA在使用的时候如果发现容量不够,是按照当前容量的1.5倍进行扩容的(当然,如果为空,则给定初始长度为10的容量)。

下面接着讲下线程安全
ArrayList是线程不安全的,为什么是线程不安全的?
其实在看源码中我们就发现,里面的操作是没有加锁。不管是add还是remove还是在扩容增加size等等,没有一个地方是加了锁的。也就是,当多个线程同时操作一个ArrayList的时候,他们都会同时对List进行修改,产生数据覆盖等异常情况。

我们再看看Vector这个同样是实现了List接口的类。


几乎所有的方法都加了synchronized关键字,来通过同步实现线程安全。可以说Vector其实就是在ArrayList的基础上加了个大锁,来解决线程不安全的。这样导致的问题是vector执行的效率是非常慢的,它不管你是不是处于高并发的状态,只要你使用了,就加锁。
那么,除了这种方式,我们平时还会使用哪些方式来解决线程不安全的呢?
1)使用LinkedList
2)使用 Collections.synchronizedList(new ArrayList())
3) 使用并发容器 CopyOnWriteArrayList

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值