工做兩年還沒看過ArrayList中remove、removeAll、clear方法源碼的都來報道吧

前言

點贊在看,養成習慣。web

點贊收藏,人生輝煌。面試

點擊關注【微信搜索公衆號:編程背鍋俠】,防止迷路。編程

刪除方法表格

方法名 描述
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++;  // 將index對應的元素賦值給 oldValue  E oldValue = elementData(index);   // 計算集合中須要移動元素個數  int numMoved = size - index - 1;  // 判斷要移動的元素個數是否大於0  if (numMoved > 0)  // 能進到這裏面要刪除的元素確定不在集合的最後面  // 若是須要移動元素個數大於0,就使用arrayCopy方法進行拷貝   // 注意:數據源和目標數據都是elementData  System.arraycopy(elementData, index+1, elementData, index,  numMoved);  // 將源集合最後一個元素置爲null,儘早讓垃圾回收機制對其進行回收  elementData[--size] = null; // clear to let GC do its work  // 返回被刪除的元素  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) {
 // 判斷要刪除的元素是否爲null  if (o == null) {  // 被刪除的元素爲null,遍歷這個集合  for (int index = 0; index < size; index++)  // 判斷集合的元素是否爲null  if (elementData[index] == null) {  // 若是相等,調用fastRemove方法快速刪除  fastRemove(index);  return true;  }  } else {  // 被刪除的元素不爲空,遍歷集合  for (int index = 0; index < size; index++)  // 用o對象的equals方法和集合每個元素進行比較  if (o.equals(elementData[index])) {  // 若是相等,調用fastRemove方法快速刪除  fastRemove(index);  return true;  }  }  // 若是集合沒有o該元素,那麼就會返回false  return false; }  // 根據索引快速刪除方法 private void fastRemove(int index) {  // 記錄修改的次數  modCount++;  // 計算要移動元素的個數  int numMoved = size - index - 1;  // 若是須要移動的個數大於0,調用arrayCopy方法進行拷貝,判斷是否是在尾部插入,大於0不是在尾部  if (numMoved > 0)  System.arraycopy(elementData, index+1, elementData, index,  numMoved);  // 將集合最後一個元素置爲null,儘早被釋放  elementData[--size] = null; // clear to let GC do its work } 複製代碼

elementData數組中元素的變化

  • 源數組中的元素 post

  • System.arraycopy執行前數組中元素 ui

  • System.arraycopy執行後數組中元素 this

總結

根據給定的元素刪除集合中與之匹配的元素。返回值爲是否刪除成功的布爾值。

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++;   // 遍歷集合,將集合每個索引對應位置上的元素都置爲null,儘早讓其釋放  for (int i = 0; i < size; i++)  elementData[i] = null;  // 集合長度更改成0  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) {
 // 將原始數組的地址賦值給elementData  final Object[] elementData = this.elementData;  // r:用於遍歷原始數組,原始數組中元素的索引, w:記錄的是未被刪除元素的個數  int r = 0, w = 0;  // modified:是否刪除成功給個默認值false  boolean modified = false;  try {  // 遍歷原始數組,size爲原始數組的長度  for (; r < size; r++)  // complement的給定的值爲false,判斷指定的集合c是否不包含這個元素  if (c.contains(elementData[r]) == complement)  // 指定的集合c中不包含原始數組中的元素,將這個元素放到elementData數組中。  // 這個循環執行完畢,elementData數組中存放的就是從索引0開始存放未被刪除的元素,和後面可能有要被刪除的和未被刪除的元素,總的長度是原始數組的size。被刪除的元素會留在原位置,未被刪除的元素原位置有一份,還有一份複製到前面。  elementData[w++] = elementData[r];  } finally {  // 正常狀況下r == size的,這個不等因而拋出了異常  if (r != size) {  // 數組的拷貝,參看個人其餘文章,有這個方法的源碼詳解  System.arraycopy(elementData, r,  elementData, w,  size - r);  // 計算修改的次數  w += size - r;  }  // 判斷w【記錄未被刪除的元素的個數】是否等於元素數組的長度  if (w != size) {  // clear to let GC do its work,方便垃圾回收,將elementData數組從索引i=w開始,置空每一個元素  for (int i = w; i < size; i++)  // 置空元素  elementData[i] = null;  // size - w刪除元素的個數,modCount記錄的是修改的次數,每刪除一個元素modCount加1  modCount += size - w;  // 刪除執行完之後集合的長度  size = w;  // 刪除成功modified 賦值爲true  modified = true;  }  }  // 返回是否刪除成功  return modified; } 複製代碼

ArrayList系列文章

第一篇:ArrayList中的構造方法源碼在面試中被問到了...抱歉沒準備好!!!告辭
第二篇:面試官讓我講ArrayList中add、addAll方法的源碼...我下次再來
第三篇:工做兩年還沒看過ArrayList中remove、removeAll、clear方法源碼的都來報道吧

創做不易, 很是歡迎你們的點贊、評論和關注(^_−)☆

你的點贊、評論以及關注是對我最大的支持和鼓勵,而你的支持和鼓勵

我繼續創做高質量博客的動力 !!!

相關文章
相關標籤/搜索