java集合类 arraylist_java集合类学习笔记之ArrayList

1、简述

ArrayList底层的实现是使用了数组保存所有的数据,所有的操作本质上是对数组的操作,每一个ArrayList实例都有一个默认的容量(数组的大小,默认是10),随着

对ArrayList不断增加元素,默认的数组会不断的向新数组进行拷贝,由于ArrayList的内部是通过对数组的操作实现的,所以它是线程不安全的

2、实现

a、构造方法:

AyyarList一共提供了三种构造方法:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/*** Constructs an empty list with the specified initial capacity.

*

*@paraminitialCapacity the initial capacity of the list

*@throwsIllegalArgumentException if the specified initial capacity

* is negative*/

public ArrayList(intinitialCapacity) {if (initialCapacity > 0) {this.elementData = newObject[initialCapacity];

}else if (initialCapacity == 0) {this.elementData =EMPTY_ELEMENTDATA;

}else{throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);

}

}/*** Constructs an empty list with an initial capacity of ten.*/

publicArrayList() {this.elementData =DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}/*** Constructs a list containing the elements of the specified

* collection, in the order they are returned by the collection's

* iterator.

*

*@paramc the collection whose elements are to be placed into this list

*@throwsNullPointerException if the specified collection is null*/

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;

}

}

View Code

在jdk1.8中,ArrayList的无参构造方法默认的是创建了一个空的数组,只有当你第一次添加是时候才会设置它的默认长度为10 ,在jdk1.6中无参构造方法默认

的就是创建一个长度为10 的空数组

b、定义内部数组:

/*** The array buffer into which the elements of the ArrayList are stored.

* The capacity of the ArrayList is the length of this array buffer. Any

* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA

* will be expanded to DEFAULT_CAPACITY when the first element is added.*/

transient Object[] elementData; //non-private to simplify nested class access

关于transient关键字的说明可以参考我的另外一篇博客 java学习笔记之对象序列化

3、ArrayList的操作

增加操作:

add(E e):

/*** Appends the specified element to the end of this list.

*

*@parame element to be appended to this list

*@returntrue (as specified by {@linkCollection#add})*/

public booleanadd(E e) {

ensureCapacityInternal(size+ 1); //Increments modCount!!

elementData[size++] =e;return true;

}

调用add(E e)方法时首先会调用ensureCapacityInternal(int minCapacity)去判断是否需要对集合进行扩容,然后默认的将新插入的对象放到内部数组的末尾,

当内部数组需要扩容时,每次直接将数组的长度值原来的两倍,这种操作的代价是很高的,所以在使用过程中我们尽量避免数组的扩容,当可以预知数组长度的时候

可以在构造的时候久指定其长度

4861f383962ad0e3013ae70ed7000049.png

add(int index, E element)

/*** Inserts the specified element at the specified position in this

* list. Shifts the element currently at that position (if any) and

* any subsequent elements to the right (adds one to their indices).

*

*@paramindex index at which the specified element is to be inserted

*@paramelement element to be inserted

*@throwsIndexOutOfBoundsException {@inheritDoc}*/

public void add(intindex, E element) {

rangeCheckForAdd(index);

ensureCapacityInternal(size+ 1); //Increments modCount!!

System.arraycopy(elementData, index, elementData, index + 1,

size-index);

elementData[index]=element;

size++;

}

在调用add(int index, E element)方法想ArrayList中插入一条数据时,这个方法内部先去判断传入的下表是否大于数组的长度。大于的话就会

抛出IndexOutOfBoundsException异常,插入的下表小于数组的长度的时候,再去判断数组是否需要扩容,最后再调用System.arraycopy方法将数组下表大于传入

的index的元素全部后移以为,并将插入的元素放到index位置

addAll(Collection extends E> c)

/*** Appends all of the elements in the specified collection to the end of

* this list, in the order that they are returned by the

* specified collection's Iterator. The behavior of this operation is

* undefined if the specified collection is modified while the operation

* is in progress. (This implies that the behavior of this call is

* undefined if the specified collection is this list, and this

* list is nonempty.)

*

*@paramc collection containing elements to be added to this list

*@returntrue if this list changed as a result of the call

*@throwsNullPointerException if the specified collection is null*/

public boolean addAll(Collection extends E>c) {

Object[] a=c.toArray();int numNew =a.length;

ensureCapacityInternal(size+ numNew); //Increments modCount

System.arraycopy(a, 0, elementData, size, numNew);

size+=numNew;return numNew != 0;

}

在调用addAll(Collection extends E> c) 插入一个集合时,这个方法内部先去判断增加这个集合数组是否需要扩容,然后调用

arraycopy(Object src, int srcPos,Object dest, int destPos,int length)方法将新增加的集合放到数组的末尾

更新操作:

public E set(intindex, E e) {

rangeCheck(index);

checkForComodification();

E oldValue= ArrayList.this.elementData(offset +index);

ArrayList.this.elementData[offset + index] =e;returnoldValue;

}

在调用set(int index,E e)方法修改里面的值时,方法内部先去检查index下表是都超过数组的最大长度,然后再检查是否有其他的线程对这个对象的长度

进行修改了(所以是线程不安全的,多线程同时操作容易直接抛异常),最后是直接替换数组中下表index对应的值

删除操作:

/*** Removes the element at the specified position in this list.

* Shifts any subsequent elements to the left (subtracts one from their

* indices).

*

*@paramindex the index of the element to be removed

*@returnthe element that was removed from the list

*@throwsIndexOutOfBoundsException {@inheritDoc}*/

public E remove(intindex) {

rangeCheck(index);

modCount++;

E oldValue=elementData(index);int numMoved = size - index - 1;if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

elementData[--size] = null; //clear to let GC do its work

returnoldValue;

}

在调用remove(int index)删除ArrayList中的数据时,首先校验传入的下标index是大于数组的长度,然后取出将要被删除的数并判断下标index之后是否还有元素,

如果有的话将下标之后的元素全部往前移动一位,并最终将删除的元素的值返回

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值