<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java進(jìn)階:深入理解ArrayList實(shí)現(xiàn)原理

          共 15677字,需瀏覽 32分鐘

           ·

          2022-06-29 16:48

          ArrayList簡(jiǎn)介

          ArrayList就是動(dòng)態(tài)數(shù)組,用MSDN中的說法,就是Array的復(fù)雜版本,它提供了動(dòng)態(tài)的增加和減少元素,實(shí)現(xiàn)了Collection和List接口,可以靈活的設(shè)置數(shù)組的大小。要注意的是ArrayList并不是線程安全的,因此一般建議在單線程中使用ArrayList。


          ArrayList的繼承關(guān)系

          public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

          由上可知ArrayList繼承AbstractList 并且實(shí)現(xiàn)了List和RandomAccess,Cloneable, Serializable接口。


          ArrayList的方法使用和源碼解析

          ①構(gòu)造方法

          //1-----------------------
          public ArrayList() {        
             this(10);        
             //調(diào)用ArrayList(10) 默認(rèn)初始化一個(gè)大小為10的object數(shù)組。
             }
          //2-------------------------
          public ArrayList(int initialCapacity) {    
                 if (initialCapacity < 0)            
                     throw new IllegalArgumentException("Illegal Capacity: "+
                                                        initialCapacity)
          ;        
                 //如果用戶初始化大小小于0拋異常,否則新建一個(gè)用戶初始值大小的object數(shù)組。                                     
                 this.elementData = new Object[initialCapacity];
             }

          //3--------------------------
          public ArrayList(Collection<? extends E> c) {
                 elementData = c.toArray();
                 size = elementData.length;        // 當(dāng)c.toArray返回的不是object類型的數(shù)組時(shí),進(jìn)行下面轉(zhuǎn)化。
                 if (elementData.getClass() != Object[].class)
                     elementData = Arrays.copyOf(elementData, size, Object[].class);
             }

          由上面三種構(gòu)造方法可知,默認(rèn)情況下使用ArrayList會(huì)生成一個(gè)大小為10的Object類型的數(shù)組。也可以調(diào)用ArrayList(int initialCapacity) 來初始化Object數(shù)組的大小。并且用戶可以往ArrayList中傳入一個(gè)容器只要這個(gè)容器是Collection類型的。調(diào)用ArrayList(Collection<? extends E> c)接口的時(shí)候會(huì)將容器數(shù)組化處理并將這個(gè)數(shù)組值賦給Object數(shù)組。

          實(shí)例:

          public static void main(String[] args) {
                 ArrayList<Integer> list_2=new ArrayList<Integer>(20);        //list_2中添加元素
                 for(int i=0;i<10;i++)
                     list_2.add(i);

                 ArrayList<Integer> list_3=new ArrayList<Integer>(list_2);        //輸出list_2中元素
                 for(Integer a:list_2)
                     System.out.print(a+" ");        //輸出list_3中元素
                 for(Integer a:list_3)
                     System.out.print(a+" ");
             }//輸出/*
          list_2 : 0 1 2 3 4 5 6 7 8 9
          -----------------------
          list_3 : 0 1 2 3 4 5 6 7 8 9
          */

          ②indexOf(Object o)方法 
          功能:查找某個(gè)元素在ArrayList中第一次出現(xiàn)的位置。

          public int indexOf(Object o) {
              //ArrayList中的元素可以為null,如果為null返回null的下標(biā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;    
                  }    
                  //如果沒有找到對(duì)應(yīng)的元素返回-1。   
                  return -1;
          }

          對(duì)于indexof方法做幾點(diǎn)說明:ArrayList中可以存放null元素,indexof是返回elementData數(shù)組中值相同的首個(gè)元素的下標(biāo),indexof中比較方法是equals而equals是比較元素的值,因此必須對(duì)null單獨(dú)查找。如果未找到該元素則返回-1 。


          public static void main(String[] args) {

                 ArrayList<Integer> list=new ArrayList<Integer>();

                 list.add(1);        
                 list.add(2);        
                 list.add(null);    
                 list.add(2);
                 list.add(3);

                 System.out.println("null: "+list.indexOf(null));
                 System.out.println("-------------------------");
                 System.out.println("2: "+list.indexOf(2));
                 System.out.println("-------------------------");
                 System.out.println("4: "+list.indexOf(4));
             }    //輸出
             /*
             null: 2
             -------------------------
             2: 1
             -------------------------
             4: -1
             */

          ③lastIndexOf(Object o)方法 
          功能:查找某個(gè)元素在ArrayList中最后出現(xiàn)的位置。

          public int lastIndexOf(Object o) {        
                 if (o == null) {        
                     //如果o為null從后往前找到第一個(gè)為null的下標(biāo)
                     for (int i = size-1; i >= 0; i--)
                         if (elementData[i]==null)                    
                             return i;
                 } else {        
                     //從后往前找到第一個(gè)值為o的下標(biāo)
                     for (int i = size-1; i >= 0; i--)                
                          if (o.equals(elementData[i]))                    
                              return i;
                 }        
                   return -1;
             }

          上面代碼做幾點(diǎn)說明:lastIndexOf(Object o)在ArrayList中從后往前找到第一個(gè)跟要查找值相同的元素的下標(biāo),因?yàn)槭前粗挡檎宜詫?duì)于 null 要單獨(dú)查找。如果未找到則返回-1;

          ④get(int index)方法 
          功能:返回ArrayList中指定下標(biāo)為index的元素。


          public E get(int index) { //檢查index的值是否大于ArrayList的大小
                 rangeCheck(index); //返回index下標(biāo)的元素      
                 return elementData(index);
             }   E elementData(int index) {        
                 return (E) elementData[index];
             }  
          //這里值檢查index >= size的情況,因?yàn)閕ndex<0時(shí)會(huì)自動(dòng)拋出異常,所以并未檢查index<0的情況。
          private void rangeCheck(int index) {        
                 if (index >= size)            
                     throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
          }

          對(duì)上面代碼做幾點(diǎn)說明:上面代碼中只檢查了index>=size的情況,在index<0的情況下也會(huì)拋出異常,只是這個(gè)異常是由系統(tǒng)拋出的。index>=size要檢查的原因是有可能數(shù)組的大小大于index,然而有效里面的元素<index這時(shí)不拋異常就會(huì)返回?zé)o效值。舉個(gè)例子ArrayList的初始化大小為10,現(xiàn)在往里面放5個(gè)元素,如果index>=5時(shí),應(yīng)該要拋出異常,而不是返回 null。因?yàn)閚ull 是可以主動(dòng)放在ArrayList中的。


          ⑤set(int index, E element)方法 
          功能:將element放到ArrayList下標(biāo)為index的位置,如果index<0或index>=size 拋異常,set(int index, E element)只能覆蓋ArrayList中原來的元素,返回值為被覆蓋的元素。

          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;
             }

          ⑥add(E e)方法 
          功能:往ArrayList中添加元素。

          public boolean add(E e) {
                 ensureCapacityInternal(size + 1);  // 加入元素前檢查數(shù)組的容量是否足夠
                 elementData[size++] = e;        
                 return true;
             }
          //2-----------------------
          private void ensureCapacityInternal(int minCapacity) {
                 modCount++;        
                 // 如果添加元素后大于當(dāng)前數(shù)組的長(zhǎng)度,則進(jìn)行擴(kuò)容
                 if (minCapacity - elementData.length > 0)
                     grow(minCapacity);
             }
          //3-----------------------  
          private void grow(int minCapacity) {        
                 // overflow-conscious code
                 int oldCapacity = elementData.length;        
                 //將數(shù)組的長(zhǎng)度增加原來數(shù)組的一半。
                 int newCapacity = oldCapacity + (oldCapacity >> 1);        
                 if (newCapacity - minCapacity < 0)
                     newCapacity = minCapacity;            
                 //如果擴(kuò)充一半后仍然不夠,則 newCapacity = minCapacity;minCapacity實(shí)際元素的個(gè)數(shù)。
                 if (newCapacity - MAX_ARRAY_SIZE > 0)
                     newCapacity = hugeCapacity(minCapacity);            
                 //數(shù)組最大位2^32
                 // minCapacity is usually close to size, so this is a win:
                 elementData = Arrays.copyOf(elementData, newCapacity);
             }

          add方法比較復(fù)雜,涉及到擴(kuò)充數(shù)組容量的問題。其中要弄清楚size和elementData.length的區(qū)別,size指的是數(shù)組中存放元素的個(gè)數(shù),elementData.length表示數(shù)組的長(zhǎng)度,當(dāng)new一個(gè)ArrayList系統(tǒng)默認(rèn)產(chǎn)生一個(gè)長(zhǎng)度為10的elementData數(shù)組,elementData.length=10,但是由于elementData中還未放任何元素所有size=0。如果加入元素后數(shù)組大小不夠會(huì)先進(jìn)行擴(kuò)容,每次擴(kuò)容都將數(shù)組大小增大一半比如數(shù)組大小為10一次擴(kuò)容后的大小為10+5=10;ArrayList的最大長(zhǎng)度為 2^32 .


          ⑦add(int index, E element)方法 
          功能:往ArrayList指定index上添加元素,添加元素后ArrayList的大小增1。index及以后的元素都會(huì)向后移一位。

          public void add(int index, E element) {
                 rangeCheckForAdd(index);//檢查index的值是否在0到size之間,可以為size。
                 ensureCapacityInternal(size + 1);  // 看elementData的長(zhǎng)度是否足夠,不夠擴(kuò)容
                 //將elementData從index開始后面的元素往后移一位。     
                 System.arraycopy(elementData, index, elementData, index + 1,
                                  size - index);
                 elementData[index] = element;
                 size++;
             }
          //2-------------------------
          private void rangeCheckForAdd(int index) {        
             if (index > size || index < 0)            
                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
             }
          //3-------------------------  
          private void ensureCapacityInternal(int minCapacity) {
                 modCount++;        
                 // overflow-conscious code
                 if (minCapacity - elementData.length > 0)
                     grow(minCapacity);
             }
          public void add(int index, E element) {
                 rangeCheckForAdd(index);//檢查index的值是否在0到size之間,可以為size。
                 ensureCapacityInternal(size + 1);  // 看elementData的長(zhǎng)度是否足夠,不夠擴(kuò)容
                 //將elementData從index開始后面的元素往后移一位。     
                 System.arraycopy(elementData, index, elementData, index + 1,
                                  size - index);
                 elementData[index] = element;
                 size++;
             }
          //2-------------------------
          private void rangeCheckForAdd(int index) {        
             if (index > size || index < 0)            
                 throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
             }
          //3-------------------------  private void ensureCapacityInternal(int minCapacity) {
                 modCount++;        
                 // overflow-conscious code
                 if (minCapacity - elementData.length > 0)
                     grow(minCapacity);
          }

          add(int index, E element)往指定index中加入元素,加入元素之前先檢查數(shù)組的大小,如果小了在原來基礎(chǔ)上增大一半,將ArrayList只能怪index及以后的元素往后移一位,將element放到index位置。


          ⑧remove(int index)方法 
          功能:刪除ArrayList指定位置的元素。

          public E remove(int index) {        
                 rangeCheck(index);//如果index>=size拋出異常
                 modCount++;
                 E oldValue = elementData(index);//獲取刪除元素的值
                 int numMoved = size - index - 1;        //將index后面所有的元素往前移一位。
                 if (numMoved > 0)
                     System.arraycopy(elementData, index+1, elementData, index,
                                      numMoved);
                 elementData[--size] = null; // Let gc do its work//返回要?jiǎng)h除的原數(shù)。
                 return oldValue;
             }

          ⑨remove(Object o)方法 
          功能:刪除ArrayList中值為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;
             }


          原文地址:

          https://blog.csdn.net/u013309870/article/details/72519272


          覺得有用就轉(zhuǎn)發(fā)分享一下吧!

          推薦

          基于 SpringBoot + Echarts 實(shí)現(xiàn)的動(dòng)態(tài)實(shí)時(shí)大屏

          我收藏的阿里云盤的資源,牛逼!!

          清華學(xué)姐自學(xué)的Linux筆記,天花板級(jí)別!

          PS:因?yàn)楣娞?hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過內(nèi)容,記得讀完點(diǎn)一下“在看”,加個(gè)“星標(biāo)”,這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。點(diǎn)“在看”支持我們吧

          瀏覽 57
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色欲av伊人网在线 | 啦啦啦www日本高清免费观看 | 男人天堂avav | 黄色片大全| 一性一交一伦一色一区二免费看 |