目录
问题2:为什么有时候使用size,有时候使用elementData.length?(如下所示)
介绍
ArrayList类又称动态数组,同时实现了Collection和List接口,其内部数据结构由数组实现,因此可对容器内元素实现快速随机访问。但因为ArrayList中插入或删除一个元素需要移动其他元素,所以不适合在插入和删除操作频繁的场景下使用。
ArrayList的容量可以随着元素的增加而自动增加,因此不用担心ArrayList容量不足的问题。(笑)
ArrayList是非线程安全的。
0)成员变量
第一个变量:扩容时后最小的大小。
第二和第三个变量为空数组,分别在构造函数参数为0和参数为空是设置。
elementData存储具体数据。
size记录实际存储元素数量。
问题1:为什么使用transient
问题2:为什么有时候使用size,有时候使用elementData.length?(如下所示)
问题3:方法中偶尔出现的modCount是什么?
翻译如下:
此列表在结构上被修改的次数。结构修改是指更改列表大小或以其他方式干扰列表,使正在进行的迭代可能会产生不正确结果的修改。此字段由迭代器和列表迭代器方法返回的列表迭代器实现使用。如果此字段的值发生意外更改,迭代器(或列表迭代器)将抛出 ConcurrentModificationException 以响应下一个、删除、上一个、设置或添加操作。这提供了快速故障行为,而不是在迭代期间面对并发修改时的非确定性行为。子类使用此字段是可选的。如果子类希望提供快速失败迭代器(并列出迭代器),那么它只需要在其add(int,E)和remove(int)方法(以及它覆盖的任何其他方法中增加此字段,从而导致对列表的结构修改)。对 add(int,E)或 remove(int) 的单个调用必须向此字段添加不超过一个,否则迭代器(和列表迭代器)将抛出虚假的ConcurrentModificationExceptions。如果实现不希望提供故障快速迭代器,则可以忽略此字段。
1)构建方法
无参构建:
int容量参数构建:
Collection实现类构建:
2)扩容Add方法
先判断是否需要扩容,再插入数据。
可以看出,在无参构造下,第一次扩容最少扩容至10大小。
看出扩容最小为=原长度+原长度右移一位长度,其余部分为最大容量的检测部分(是否需要报错异常超出最大容量OutOfMemoryError)
溢出,数据最高位符号位为1,变为负数。
3)remove方法
可以看出,仅是使用System.arraycopy方法处理,不会进行缩容操作。使最后数组一位为空,去除引用关系,便于GC清除。
4)clone克隆方法
追踪可知,最终调用native方法:System.arraycopy。
5)clear清空方法
不会创建一个空对象数组。也不缩容。
6)trimToSize调整容量
缩容,减少占用空间大小。
在JSONParser序列化中有使用到。
7)contains方法
可以查询null对象。
使用equals比较对象。
返回第一个匹配的下标。
8)forEach方法
传递操作类,实现其accept方法进行具体操作。
注意,尽量不要用该方法修改elementData数据,除非了解到数据是否可以修改(!???)
例(修改final对象,X):
@Test
public void test11() {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(6);
list.add(11);
list.add(21);
list.forEach(e -> e = e + 1);
System.out.println(list);
}
out---------------Integer是final类!!----------
[1, 6, 11, 21]
例(stream修改法,或者老老实实for循环):
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(6);
list.add(11);
list.add(21);
List<Integer> collect = list.stream().map(e -> e = e + 1).collect(Collectors.toList());
System.out.println(collect);
out----------------------------------
[2, 7, 12, 22]
例(修改对象中内容,可):
public class FinallyTest {
public int a = 0;
FinallyTest(int a) {
this.a = a;
}
FinallyTest() {
this.a = 0;
}
@Override
public String toString() {
return "FinallyTest{" +
"a=" + a +
'}';
}
}
class TestT {
@Test
public void test11() {
ArrayList<FinallyTest> list2 = new ArrayList<>();
list2.add(new FinallyTest(1));
list2.add(new FinallyTest(6));
list2.add(new FinallyTest(11));
list2.add(new FinallyTest(21));
list2.forEach(e -> e.a += 10);
System.out.println(list2);
}
}
out--------------------------------
[FinallyTest{a=11}, FinallyTest{a=16}, FinallyTest{a=21}, FinallyTest{a=31}]
总结:
要不是没有女朋友,谁写这个???(5/20日写)
参考: