ArrayList源码基本理解。

前言

    有些人死了,他还活着,有些人活着,他已经死了。秋天到了,万物复苏。
    List是一个接口,List中存的元素是有序可重复的。工作中比较常用的就是ArrayList,本文就聊一下个人对于ArrayList的理解。题外话,为了面试,也要对LinkedList和Vector有所了解 。

ArrayList

    ArrayList的底层是Object[],这就不用多BB了吧!每一个看过源码或者背过八股文的人都知道!

  1.构造方法

    概述:1.无参的构造器会创建一个空的Object[]
    2.参数为int的构造器,会创建一个空的Object[]或者长度为参数的Object[]
    3.参数为集合的构造器,会创建一个空的Object[]或者将集合转换为Object[]

无参构造方法: //创建一个空的Object[] 
public ArrayList() {
	this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
带参构造方法1://传入一个int类型参数,
如果大于0,则创建该长度的Object[];
如果为0,则创建一个空的Object[];
如果小于0,则抛出异常。
public ArrayList(int initialCapacity) {
	if (initialCapacity > 0) {
		this.elementData = new Object[initialCapacity];
	} else if (initialCapacity == 0) {
		this.elementData = EMPTY_ELEMENTDATA;
	} else {
		throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
	}
}
带参构造方法2://传入一个Collection 
将该集合转换为数组;
判断数组长度是否为0,如果不为0,则判断是否为Object数组,如果不是则转换为Object[];
如果数组长度为0,则重新赋值为空的Object[]

public ArrayList(Collection<? extends E> c) {
	elementData = c.toArray();
	if ((size = elementData.length) != 0) {
		// c.toArray might (incorrectly) not return Object[] (see 6260652)
		if (elementData.getClass() != Object[].class)
			elementData = Arrays.copyOf(elementData, size, Object[].class);
	} else {
		// replace with empty array.
		this.elementData = EMPTY_ELEMENTDATA;
	}
}

  2.添加元素–>add(E e)

    概述:该方法会首先判断是否需要扩容,然后将元素添加的数组中

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  //判断数组是否需要扩容
        elementData[size++] = e;//数组长度+1,并将e放入数组中
        return true;
    }

  3.添加元素–>add(int index, E element)

    概述:该方法会首先判断是否数组越界,然后判断需要扩容,然后将元素添加的数组指定下标位置

//判断是否越界,不越界则判断是否扩容,然后移动数据
public void add(int index, E element) {
        rangeCheckForAdd(index);//判断是否数组越界

        ensureCapacityInternal(size + 1);  // 判断数组是否需要扩容
        System.arraycopy(elementData, index, elementData, index + 1, size - index);//将index以后的元素向后移动
        elementData[index] = element;//将新元素放入数组,下标为index
        size++;//数组长度+1
}

  4.获取元素–> get(int index)

    概述:该方法会首先判断是否数组越界,然后去数组中获取指定下标的元素

public E get(int index) {
        rangeCheck(index);//判断是否数组越界
        return elementData(index);//返回下标为index的元素
}

  5.扩容

    概述:扩容机制也很简单,就是创建一下新的数组,数组长度为旧数组的1.5倍

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;//设置旧长度=数组长度;
        int newCapacity = oldCapacity + (oldCapacity >> 1);//设置新长度为旧长度+旧长度>>1(可以理解为扩容1.5倍)
        if (newCapacity - minCapacity < 0)//minCapacity 为add方法中传来的,新加元素后,需要的数组长度,如果新长度-需要的长度小于0,则新长度重新赋值为minCapacity 
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)//如果新长度超过了最大长度,则新长度为最大长度
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);//复制数组元素到新数组里
 }

  6.indexOf

    下雨天打孩子,闲着也是闲着,再看看indexOf方法吧(lastIndexOf同理就不展开了)

public int indexOf(Object o) {//根据元素,获取元素下标
        if (o == null) {//判断是否为空
            for (int i = 0; i < size; i++)//遍历数组
                if (elementData[i]==null)//找到元素值为null的下标并返回该下标
                    return i;
        } else {//元素不是null
            for (int i = 0; i < size; i++)//遍历数组,找到相等的元素并返回下标
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;//找不到,返回-1
}
    //综上,这个方法贼98k简单,算一下时间复杂度是多少呢?O(n)。你真聪明!

总结

    ArrayList查询速度比较快,时间复杂度为O(1);
    ArrayList增删比较慢,可能需要移动元素,时间复杂度X,O(1)≤X≤O(n)(一般直接说O(n));我相信以你的聪明才智,你肯定知道是怎么计算的。
    
    至此,我们已经看完了ArrayList中常用的方法了。本人水平有限,如果有不对的地方,敬请指正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值