Collection集合List

一、有序列表List接口:

1、常见实现

有三种实现方式:ArrayList、Vector和LinkedList,都是同一个接口的实现,所以操作和方法都是相同的,但是具体的实现方式不一样。
(1)ArrayList:数组实现方式,查询速度快,按位增删速度慢;
(2)LinkedList:链表的实现方式,按位增删速度快,查询速度慢;

(3)Vector:多线程时线程同步的,保证数据安全。

二、ArrayList:

1、原理:

内部是数组实现;

2、线程安全问题:

线程不安全。底层是一个数组,多个线程会修改长度。

public class ContainerNotSafeTest {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for(int i = 0; i < 30; i++){
            int tempInt = i;
            new Thread(()->{
                list.add(tempInt);
                System.out.println(list);
            }).start();
        }
    }
}

线程不安全解决方法

(1)使用 Vector。List的古老实现类,JDK1.0引入;

   

(2)Collections工具类的synchronizedList方法

List<String> list = Collections.synchronizedList(new ArrayList<>());

(3)CopyOnWriteArrayList写时复制技术

List<String> list = new CopyOnWriteArrayList<>();
 3、扩容

1)new无参对象时,底层是一个空数组;

2)当添加第一个元素时,会进行扩容,将底层数组长度扩为10,其中扩容触发的条件是:存元素时,即先让size+1的值判断是否大于底层elementData.length的长度,如果大于,则先扩容再添加,扩容的倍数为1.5倍,数组长度在有小数时会向下取整比如说:在效果图数组长度15时:在添加第16个元素时扩容后的长度为:原来长度*0.5+原来长度(向下取整)=新长度;运用这个公式就可以得到新的扩容数组长度为22。

通过查看源码看下详细过程:

3.1、初始化:

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

可以发现它的底层其实是一个Object类型的数组变量elementData(其实后面添加的元素就是存入这个数组中),初始化是空。

注意:当然我们也可以设置长度为其他值

例如:  ArrayList list=new  ArrayList<>(50); 当我们打印集合长度是就为:50

好处:可以减少扩容次数,提高程序在处理,运行时的速度

3.2、添加第一个元素

接下来执行 ensureCapacityInternal(size + 1)这个方法,就是去检测以下容器(elelmentData数组)长度是否够用,将size+1的值作为是否触发扩容的标准,这个值满足内在的设计条件,则扩容,不满足就不扩容,表示elementData数组容量还凑合,暂时不加长了。

注意:size其实代表的就是我们实际放入集合中的元素个数(而非elementData.length)。

private int size;
public boolean add(E e) {
// 将size+1的值作为判断接下来要不要扩容的标准,具体代码就在下一个方法, 
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
protected transient int modCount = 0;
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

     private void grow(int minCapacity) {//minCapacity=10
        int oldCapacity = elementData.length;//此时elementData依然是空数组,长度自然为0,因此oldCapacity=0
        int newCapacity = oldCapacity + (oldCapacity >> 1);```
         **>>1 这个表示是二进制右移一位,0右移一位依然是0,因此newCapacity=0+0=0,后面当添加到11个元素时,也会在此扩容,扩容后的长度就是这样子算的,  10+10>>1   右移1位相当于乘以0.5 ,因此newCapacity=10+10*0.5=15  ,也就是说,扩容倍数为1.5倍**
   ```java      
        if (newCapacity - minCapacity < 0)//minCapacity:传入方法参数值10,   0-10=-10<0 为true,if成立
            newCapacity = minCapacity;	//将10赋值给新的数组长度   newCapacity=10
        if (newCapacity - MAX_ARRAY_SIZE > 0)// MAX_ARRAY_SIZE =int的4个字节一共32位bit的最大值大概21亿多减去8的值,显然不成立
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);//通过Arrays工具类将老数组内容复制到一个新的数组,并指定此数组的长度为newCapacity:10   ,因此grow完成了扩容,返回的是长度为10的数组,里面存了系统给的默认值10个null。 
    }

补充:a >> b,则移动后a = a / 2^b,源码中

int newCapacity = oldCapacity + (oldCapacity >> 1);

右移1位,所以newCapacity = oldCapacity  + oldCapacity / 2,即扩容为1.5倍。

二、LinkedList:

1、底层原理:LinkedList的实现是基于双向链表的,且头结点中不存放数据。双向链表不仅存储下一处的地址,还存储上一处的。

(1)随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
(2)增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。

2、线程安全问题:线程不安全。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_t_y_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值