ArrayList数组
ArrayList
数据结构
底层数据接口是根据动态数组存储数据,根据System.arraycopy()
方法去动态扩容。
ArrayList和LinkedList对比
因为底层数据结构是数组,所以获取元素的很快,但新增元素或删除元素时,如果涉及到数组拷贝则效率会很慢,所以在使用时最好指定数组的长度,防止频繁的进行数组的拷贝,如果频繁的进行删除和新增则可以使用
LindekList
进行存储数据,因为LinkedList
底层是双向链表,只需要改变上一个元素或下一元素的指向则可进行删除和新增,效率会比ArrayList
更高因为底层数据结构的不同,占用的空间会小于
LinkedList
但ArrayList
每次扩容大小都是当前数组长度的1.5倍,所以会浪费内存空间所以如果你对内存占用敏感并且频繁访问元素,
ArrayList
可能是更好的选择。如果你频繁插入和删除元素,尤其是在中间位置,LinkedList
会更适合
核心字段
字段 | 含义 | 代码 |
---|---|---|
DEFAULT_CAPACITY | 默认大小 | private static final int DEFAULT_CAPACITY = 10 |
elementData | 数据存储 | transient Object[] elementData |
size | 数组大小 | private int size |
DEFAULTCAPACITY_EMPTY_ELEMENTDATA | 用于默认大小的空实例的共享空数组实例 | private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; |
构造方法
无参构造方法
1
2
3
4
5
6/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}指定数组长度的构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
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);
}
}根据传入的集合去构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
Object[] a = c.toArray();
if ((size = a.length) != 0) { // 判断是否是空数组
if (c.getClass() == ArrayList.class) {
elementData = a; // 如果类型是ArryList则直接指向
} else {
elementData = Arrays.copyOf(a, size, Object[].class); // 如果不是则进行拷贝
}
} else {
// replace with empty array. 如果是空数组则默认为{}
elementData = EMPTY_ELEMENTDATA;
}
}
添加元素
在行尾添加元素
1
2
3
4
5
6
7
8
9
10
11/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}在指定下标添加元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/**
* 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).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheckForAdd(index); // 判断添加的下标是否大于数组长度,如果大于则抛出IndexOutOfBoundsException数组下标越界的异常
modCount++; // 操作次数+1
final int s;
Object[] elementData;
if ((s = size) == (elementData = this.elementData).length)
elementData = grow(); // 扩容大小:1
System.arraycopy(elementData, index,
elementData, index + 1,
s - index); //指定下标后的元素下标往后移动一位
elementData[index] = element; // 在指定下标添加元素
size = s + 1; // 数组大小+1
}添加集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27/**
* 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.)
*
* @param c collection containing elements to be added to this list
* @return {@code true} if this list changed as a result of the call
* @throws NullPointerException if the specified collection is null
*/
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
modCount++; // 操作次数+1
int numNew = a.length; // 获取传入的数组长度
if (numNew == 0)
return false;// 如果为空返回false
Object[] elementData;
final int s;
if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew); // 如果传入的数组大小大于当前数组的长度(总长度-实际长度)则数组扩容
System.arraycopy(a, 0, elementData, s, numNew); // 将传入的数组拷贝到队尾中
size = s + numNew; // 当前数组大小加上传入数组的大小
return true;
}在指定下标添加集合元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37/**
* Inserts all of the elements in the specified collection into this
* list, starting at the specified position. Shifts the element
* currently at that position (if any) and any subsequent elements to
* the right (increases their indices). The new elements will appear
* in the list in the order that they are returned by the
* specified collection's iterator.
*
* @param index index at which to insert the first element from the
* specified collection
* @param c collection containing elements to be added to this list
* @return {@code true} if this list changed as a result of the call
* @throws IndexOutOfBoundsException {@inheritDoc}
* @throws NullPointerException if the specified collection is null
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index); // 判断添加的下标是否大于数组长度,如果大于则抛出IndexOutOfBoundsException数组下标越界的异常
Object[] a = c.toArray();
modCount++; // 操作次数+1
int numNew = a.length;
if (numNew == 0)
return false;
Object[] elementData;
final int s;
if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew); // 如果传入的数组大小大于当前数组的长度(总长度-实际长度)则数组扩容.扩容的大小=(当前数组长度+传入的数组长度)*1.5
int numMoved = s - index; // 需要移动下标的大小
if (numMoved > 0)
System.arraycopy(elementData, index,
elementData, index + numNew,
numMoved); // 将传入的下标后的元素后移numMoved大小
System.arraycopy(a, 0, elementData, index, numNew); // 数组拷贝
size = s + numNew; // 当前数组长度+传入的数组长度
return true;
}
删除元素
根据元素删除
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44/**
* Removes the first occurrence of the specified element from this list,
* if it is present. If the list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* {@code i} such that
* {@code Objects.equals(o, get(i))}
* (if such an element exists). Returns {@code true} if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return {@code true} if this list contained the specified element
*/
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found: { // 获取元素的下标
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false;
}
fastRemove(es, i); // 根据下标删除数据(只删除第一个找到的元素,如果有多个相同元素,则不会全部删除)
return true;
}
/**
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(Object[] es, int i) {
modCount++; // 操作次数+1
final int newSize;
if ((newSize = size - 1) > i) // 如果不是队尾元素则将将指定下标处的元素网球移动一位
System.arraycopy(es, i + 1, es, i, newSize - i);
es[size = newSize] = null; // 删除元素后,将数组末尾的元素置为 null
}根据下标删除元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*
* @param index the index of the element to be removed
* @return the element that was removed from the list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
Objects.checkIndex(index, size); // 判断是否下标越界,如果越界则抛出数组下标越界的异常 IndexOutOfBoundsException
final Object[] es = elementData;
E oldValue = (E) es[index]; // 根据删除坐标获取删除元素的内容
fastRemove(es, index); // 调用的方法和根据元素删除的调用的方法一致
return oldValue; // 返回删除元素的内容
}根据下标范围批量删除元素 (待补充)
根据传入的集合元素批量删除 (待补充)
动态扩容
System.arraycopy()
简介
arraycopy是java.lang.system类下方法
源码
1 | public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, |
参数简介
参数 | 数据结构 | 含义 |
---|---|---|
length | int | 要复制的数组元素的数量,一般为src.length-srcPos |
src | Object | 源数组 |
srcPos | int | 从源数组的该下标之后开始拷贝 |
dest | int | 目标数组 |
destPos | Object | 从目标数组的该下标之后替换为源数据的数据 |
代码示例
1 | public static void main(String[] args) { |
源码
1 | private Object[] grow(int minCapacity) { |
流程图

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ting-个人博客!