前言
点赞在看,养成习惯。
点赞收藏,人生辉煌。
点击关注【微信搜索公众号:编程背锅侠】,第一时间获得最新文章。
看源码血泪史
刚开始工作面试的时候,面试官经常问ArrayList源码相关的问题,基本上都是这部分很快结束战斗。
面试官:你看过ArrayList的源码吗?我:你肯定会说看过呀。面试官:那你来讲讲你对ArrayList源码的理解吧。我:底层的数据结构是object数组;增删快、查询慢等等,没说几句就完了。
其实看了ArrayList的源码以后,你会发现能说的点还是有很多的。 比如ArrayList的构造方法的底层数组真的是构造了一个长度为10的数组吗? Arrays.copy方法,grow扩容方法是怎么扩容的?等等都可以细说。 ArrayList的源码从工作到现在大概看了不下10遍,这其中包括看了半道放弃的。 刚开始看源码是在一些博客网站上看,看的稀里糊涂不是很明白,越看越想放弃。 后面看了一些公开课,跟着老师讲的视频看源码,看完之后感觉有点意思。但是看完之后,自己单独看还是有点吃力。 2020年4月份的时候看了一遍ArrayList源码并且每行都做了注释,整理在了有道上。 现在是七月初时隔两个月在再次看源码发现以前的笔记有部分是模糊、或者理解不正确的。 目前我发布出来的ArrayList源码是我一步一步DEBUG调试验证的源码。如果理解有问题看过之后,还请多多指教。
ArrayList系列文章
第一篇:ArrayList中的构造方法源码在面试中被问到了…抱歉没准备好!!!告辞 第二篇:面试官让我讲ArrayList中add、addAll方法的源码…我下次再来 第三篇:工作两年还没看过ArrayList中remove、removeAll、clear方法源码的都来报道吧 第四篇: 乱披风锤法锤炼ArrayList源码中的get、set、contains、isEmpty方法!!!肝起来 第五篇: 满屏飘红,操作ArrayList的Iterator方法时竟然给我报ConcurrentModificationException异常,撸ta
删除方法表格
方法名描述
public E remove(int index)根据索引删除元素public boolean remove(Object o)根据元素删除元素public void clear()将集合清空public boolean removeAll(Collection<?> c)删除与给定集合中相同的元素
public E remove(int index) 根据索引删除元素
案例演示
@Test
public void test_remove_index(){
ArrayList
<String> list
= new ArrayList<>();
list
.add("洛洛01");
list
.add("洛洛02");
list
.add("洛洛03");
list
.forEach(System
.out
::println
);
list
.remove(1);
list
.forEach(System
.out
::println
);
}
源码分析
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
;
}
elementData数组中元素的变化
源数组中的元素
System.arraycopy执行前数组中元素
System.arraycopy执行后数组中元素-1
System.arraycopy执行后数组中元素-2
总结
根据索引删除元素,返回被删除的元素。重点关注elementData数组中元素的变化,可以帮助理解。
System.arraycopy方法不明白的参考这篇文章
public boolean remove(Object o) 根据元素删除元素
案例演示
@Test
public void test_remove_v(){
ArrayList
<String> list
= new ArrayList<>();
list
.add("洛洛01");
list
.add("洛洛02");
list
.add("洛洛03");
list
.add("洛洛04");
list
.forEach(System
.out
::println
);
list
.remove("洛洛03");
list
.forEach(System
.out
::println
);
}
源码分析
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
;
}
elementData数组中元素的变化
源数组中的元素
System.arraycopy执行前数组中元素
System.arraycopy执行后数组中元素
总结
根据给定的元素删除集合中与之匹配的元素。返回值为是否删除成功的布尔值。
System.arraycopy方法不明白的参考这篇文章
public void clear()将集合清空
案例演示
@Test
public void test_clear(){
ArrayList
<String> list
= new ArrayList<>();
list
.add("洛洛01");
list
.add("洛洛02");
list
.forEach(System
.out
::println
);
list
.clear();
list
.forEach(System
.out
::println
);
}
源码分析
public void clear() {
modCount
++;
for (int i
= 0; i
< size
; i
++)
elementData
[i
] = null
;
size
= 0;
}
elementData数组中元素的变化
源数组中的元素
清空以后的数组
总结
将集合清空。这个方法会将集合每一个索引对应位置上的元素都置为null,为的是尽早让垃圾收集器回收。
public boolean removeAll(Collection<?> c)删除与给定集合中相同的元素
案例演示
@Test
public void test_remove_all(){
ArrayList
<String> list
= new ArrayList<>();
list
.add("洛洛01");
list
.add("洛洛02");
list
.forEach(System
.out
::println
);
ArrayList
<String> all
= new ArrayList<>();
all
.add("洛洛01");
all
.add("洛洛05");
list
.removeAll(all
);
list
.forEach(System
.out
::println
);
}
源码分析
public boolean removeAll(Collection
<?> c
) {
Objects
.requireNonNull(c
);
return batchRemove(c
, false);
}
elementData数组中元素的变化
源数组中的元素
源数组变化以后的元素
总结
删除与给定集合中相同的元素。这个方法的主要实现是batchRemove方法。
private boolean batchRemove(Collection<?> c, boolean complement)批量删除方法
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
;
}
创作不易, 非常欢迎大家的点赞、评论和关注(^_−)☆ 你的点赞、评论以及关注是对我最大的支持和鼓励,而你的支持和鼓励 我继续创作高质量博客的动力 !!!