本质:数组
两个成员(属性),
elementData和
size
1.new
new的时候给
elementData赋值了一个空数组
private
static
final
Object[]
EMPTY_ELEMENTDATA
= {};
/**
* 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 == EMPTY_ELEMENTDATA will be expanded to
* DEFAULT_CAPACITY when the first element is added.
*/
private
transient
Object[]
elementData
;
/**
* The size of the ArrayList (the number of elements it contains).
*
*
@serial
*/
private
int
size
;
/**
* 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
) {
super
();
if
(
initialCapacity
< 0)
throw
new
IllegalArgumentException(
"Illegal Capacity: "
+
initialCapacity
);
this
.
elementData
=
new
Object[
initialCapacity
];
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
public
ArrayList() {
super
();
this
.
elementData
=
EMPTY_ELEMENTDATA
;
}
如果new的时候给了一个长度,但是并不会立马体现在size上
如下,只是new了一个这样长度的数组
public
ArrayList(
int
initialCapacity
) {
super
();
if
(
initialCapacity
< 0)
throw
new
IllegalArgumentException(
"Illegal Capacity: "
+
initialCapacity
);
this
.
elementData
=
new
Object[
initialCapacity
];
}
2.size()
很尴尬,返回了private的size属性
public
int
size() {
return
size
;
}
3.add()
public
boolean
add(E
e
) {
ensureCapacityInternal(
size
+ 1);
// Increments modCount!!增加mod数,我猜是增加操作的次数,记录下操作了多少次
//并且其中如果数组长度太小,则增加数组长度
elementData
[
size
++] =
e
;
return
true
;
}
4.add(index,element)
public
void
add
(
int
index
, E
element
) {
rangeCheckForAdd(
index
); //判断index是否正确,不正确抛异常
ensureCapacityInternal(
size
+ 1);
// Increments modCount!!
System.
arraycopy
(
elementData
,
index
,
elementData
,
index
+ 1,
size
-
index
);
elementData
[
index
] =
element
;
size
++;
}
5.remove(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
;
// clear to let GC do its work
return
oldValue
;
}
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
;
// clear to let GC do its work
}
6.get/set
@SuppressWarnings
(
"unchecked"
)
E elementData(
int
index
) {
return
(E)
elementData
[
index
];
}
public
E get(
int
index
) {
rangeCheck(
index
);
return
elementData(
index
);
}
public
E set(
int
index
, E
element
) {
rangeCheck(
index
);
E
oldValue
= elementData(
index
);
elementData
[
index
] =
element
;
return
oldValue
;
}
..contains,indexOf
public
boolean
contains(Object
o
) {
return
indexOf
(
o
) >= 0;
}
public
int
indexOf
(Object
o
) {
if
(
o
==
null
) {
for
(
int
i
= 0;
i
<
size
;
i
++)
if
(
elementData
[
i
]==
null
)
return
i
;
}
else
{
for
(
int
i
= 0;
i
<
size
;
i
++)
if
(
o
.equals(
elementData
[
i
]))
return
i
;
}
return
-1;
}
public
int
lastIndexOf(Object
o
) {
if
(
o
==
null
) {
for
(
int
i
=
size
-1;
i
>= 0;
i
--)
if
(
elementData
[
i
]==
null
)
return
i
;
}
else
{
for
(
int
i
=
size
-1;
i
>= 0;
i
--)
if
(
o
.equals(
elementData
[
i
]))
return
i
;
}
return
-1;
}
总结
:
1). ArrayList实际上是通过一个数组去保存数据的,当我们构造ArrayList时,如果使用默认构造函数,ArrayList的默认容量大小是10。
2). 当ArrayList容量不足以容纳全部元素时,ArrayList会自动扩张容量,新的容量 = 原始容量 + 原始容量 / 2。
int
newCapacity
=
oldCapacity
+ (
oldCapacity
>> 1);(1.7可能与1.6版本不太一样)
3). ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
4). ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写出“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
5). 在做ArrayList的遍历的时候有3中遍历的方法,分别是随机访问遍历,用迭代器遍历和强制for循环遍历,按照效率来说最快的是随机访问遍历,最差的是迭代器遍历。
6). ArrayList的遍历是不安全的,在遍历的时候如果改变了集合的结构会抛出ConcurrentModificationException异常。也就是快速失败机制(fail-fast机制),在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时或者当遍历操作的数量大大超过可变操作的数量时,可以用CopyOnWriteArrayList来替代ArrayList。CopyOnWriteArrayList核心机制是任何对array在结构上有所改变的操作(add、remove、clear等),CopyOnWriterArrayList都会copy现有的数据,再在copy的数据上修改,
这样就不会影响COWIterator中的数据了,修改完成之后改变原有数据的引用即可。同时这样造成的代价就是产生大量的对象,同时数组的copy也是相当有损耗的。
在遍历过程中,不能删除!!!
超级for中会报错,普通for循环中,会遍历不到你删除的元素下个元素