【源码】ArrayList源码
前言构造方法add插入元素get(int index)获取元素contains(Object o)判断元素是否存在remove(int index)根据下标移除元素remove(Object o)移除元素removeAll(Collection c)
前言
作为最常用的集合之一,有必要读一下源码。 ArrayList,基于数组实现,因此元素的读取速度十分快,因为数组在内存的上地址连续,但是插入删除涉及到数组元素的移动,因此效率较低。
构造方法
public ArrayList() {
super();
this.elementData
= EMPTY_ELEMENTDATA
;
}
transient Object
[] elementData
;
private static final Object
[] EMPTY_ELEMENTDATA
= {};
public ArrayList(Collection
<? extends E> c
) {
elementData
= c
.toArray();
size
= elementData
.length
;
if (elementData
.getClass() != Object
[].class)
elementData
= Arrays
.copyOf(elementData
, size
, Object
[].class);
}
构造方法比较简单,我们平时最常用的默认构造,初始化内部数组为空数组。
add插入元素
public boolean add(E e
) {
ensureCapacityInternal(size
+ 1);
elementData
[size
++] = e
;
return true;
}
private void ensureCapacityInternal(int minCapacity
) {
if (elementData
== EMPTY_ELEMENTDATA
) {
minCapacity
= Math
.max(DEFAULT_CAPACITY
, minCapacity
);
}
ensureExplicitCapacity(minCapacity
);
}
private static final int DEFAULT_CAPACITY
= 10;
private void ensureExplicitCapacity(int minCapacity
) {
modCount
++;
if (minCapacity
- elementData
.length
> 0)
grow(minCapacity
);
}
private void grow(int minCapacity
) {
int oldCapacity
= elementData
.length
;
int newCapacity
= oldCapacity
+ (oldCapacity
>> 1);
if (newCapacity
- minCapacity
< 0)
newCapacity
= minCapacity
;
if (newCapacity
- MAX_ARRAY_SIZE
> 0)
newCapacity
= hugeCapacity(minCapacity
);
elementData
= Arrays
.copyOf(elementData
, newCapacity
);
}
public void add(int index
, E element
) {
rangeCheckForAdd(index
);
ensureCapacityInternal(size
+ 1);
System
.arraycopy(elementData
, index
, elementData
, index
+ 1,
size
- index
);
elementData
[index
] = element
;
size
++;
}
插入元素第一件事就是根据插入后的长度判断是否需要扩容,由于默认构造为空数组,因此第一次插入会发生一次扩容。在指定位置的元素插入会涉及整个元素的移动,因此调用的是native方法,效率较高。
get(int index)获取元素
public E
get(int index
) {
rangeCheck(index
);
return elementData(index
);
}
contains(Object o)判断元素是否存在
public boolean contains(Object o
) {
return indexOf(o
) >= 0;
}
remove(int index)根据下标移除元素
public E
remove(int index
) {
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
;
return oldValue
;
}
remove(Object o)移除元素
public boolean remove(Object o
) {
if (o
== null
) {
for (int index
= 0; index
< size
; index
++)
if (elementData
[index
] == null
) {
fastRemove(index
);
return true;
}
} else {
for (int index
= 0; index
< size
; index
++)
if (o
.equals(elementData
[index
])) {
fastRemove(index
);
return true;
}
}
return false;
}
private void fastRemove(int index
) {
modCount
++;
int numMoved
= size
- index
- 1;
if (numMoved
> 0)
System
.arraycopy(elementData
, index
+1, elementData
, index
, numMoved
);
elementData
[--size
] = null
;
}
removeAll(Collection c)
public boolean removeAll(Collection
<?> c
) {
Objects
.requireNonNull(c
);
return batchRemove(c
, false);
}
private boolean batchRemove(Collection
<?> c
, boolean complement
) {
final Object
[] elementData
= this.elementData
;
int r
= 0, w
= 0;
boolean modified
= false;
try {
for (; r
< size
; r
++)
if (c
.contains(elementData
[r
]) == complement
)
elementData
[w
++] = elementData
[r
];
} finally {
if (r
!= size
) {
System
.arraycopy(elementData
, r
,
elementData
, w
,
size
- r
);
w
+= size
- r
;
}
if (w
!= size
) {
for (int i
= w
; i
< size
; i
++)
elementData
[i
] = null
;
modCount
+= size
- w
;
size
= w
;
modified
= true;
}
}
return modified
;
}