<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專欄:以動畫的方式帶你深入理解Java源碼ArrayList!!!

          共 1788字,需瀏覽 4分鐘

           ·

          2022-03-01 02:55

          大家好,我是老黑[1]

          今天我們來研究研究Java集合ArrayList的源碼,廢話不多說,開搞。

          先拋出幾個問題:

          • 你是否知道ArrayList的存儲原理?
          • 你是否知道ArrayList的擴容原理?
          • 你知道ArrayList什么時候擴容嗎?
          • 你知道ArrayList是線程安全的嗎?
          • 你知道ArrayList與LinkedList的區(qū)別嗎?

          (答案與ArrayList生命周期動畫放在文末~)

          再預(yù)覽一下本文大綱:

          ArrayList概述

          ArrayList是Java語言中最常見的集合工具類之一,它繼承AbstractList,實現(xiàn)了以下接口:

          • List(列表)

          • RandomAccess(順序訪問)

          • Cloneable(可克?。?/p>

          • Serializable(可序列化)


          從它的繼承與實現(xiàn)來看,ArrayList是一個可克隆,可序列化,可順序訪問的列表。


          ArrayList的存儲原理

          在ArrayList中,內(nèi)部擁有4個屬性:

          ArrayList繼承關(guān)系與屬性

          從上圖發(fā)現(xiàn),ArrayList的實現(xiàn)原理內(nèi)部其實是一個對象數(shù)組:Object[],然后還有一個屬性size用來表示鏈表的實際長度。

          源碼分析

          add(E object)

          add(E object)

          add(int index, E object)

          add(int index, E object)

          請問:這個方法是線程安全的嗎?

          我們再看一個動畫演示:

          所以,add(int index, E object)不是線程安全的。

          remove(int index)

          remove(int index)

          remove(Object o)

          remove(Object o)

          set(int index, E object)

          set(int index, E object)

          修改與刪除不同,修改沒有類似CAS(比較并且交換)的API。

          在這里多提一嘴,我們要知道,一個列表存放的到底是什么?

          沒錯,存放的是對象的地址,而不是真正的對象,下面再來看一下動畫演示如何修改的:

          查詢比較簡單,直接根據(jù)下標獲取數(shù)據(jù)即可。

          get(int index)

          迭代器

          ArrayList.Itr迭代器

          ArrayList的內(nèi)部類Itr迭代器

          迭代器的這些方法其實都是我們經(jīng)常會使用到的,hasNext、next、remove等等。

          Itr的next方法
          Itr的remove方法

          小結(jié):

          1. 使用迭代器后,在迭代器外部最好是不要操作列表,否則在后續(xù)使用這個迭代器時很有可能將拋出異常;
          2. 使用next之前一般都會使用hasNext進行判斷;
          3. 使用remove之前必須使用next方法;
          4. 使用remove方法后迭代器內(nèi)部的expectedModCount會同步更新,所以在迭代器內(nèi)部remove是允許的;
          5. remove方法不允許連續(xù)使用兩次,因為在第一次使用后lastRet就會置為-1,下次remove時判斷l(xiāng)astRet<0則拋出IllegalStateException。

          ArrayList.ListItr迭代器

          ListItr是繼承了Itr的,所以Itr的所有功能在ListItr都有。

          ListItr與Itr的區(qū)別是:

          • Itr只能從前往后迭代,并且是不允許查找上一個數(shù)據(jù);

          • 而ListItr則允許從前往后和從后往前兩種迭代方向,同時也允許查找上一個數(shù)據(jù),并且也允許從中間某一個位置開始遍歷。

          遍歷方式

          準備

          List?list?=?new?ArrayList();
          list.add("1");
          list.add(2);
          list.add("3");
          list.add(4);

          for循環(huán)

          for?(int?i?=?0;?i?????Object?obj?=?list.get(i);
          ????System.out.println(obj);
          ?
          ????//?remove
          ????//?不推薦,原因:內(nèi)部會進行數(shù)組塊移動,性能低
          ????//?list.remove(obj);
          }

          增強for循環(huán):foreach

          //?foreach遍歷的本質(zhì)是迭代器遍歷
          for?(Object?obj?:?list)?{
          ????System.out.println(obj);
          ?
          ????//?remove
          ????//?反對,原因:如果在里面remove元素的話,會拋ConcurrentModificationException異常
          ????//?list.remove(obj);
          }

          老黑在這里額外提一嘴,foreach遍歷的本質(zhì)是迭代器遍歷,所以,在迭代器遍歷的時候,使用list.remove方法,會修改list內(nèi)部的modCount,而迭代器內(nèi)部的expectedModCount并沒有改變,所以在下一次迭代的時候,迭代器內(nèi)部檢查將會拋出ConcurrentModificationException異常。

          迭代器遍歷(推薦)

          Iterator?iterator?=?list.iterator();
          while?(iterator.hasNext())?{
          ????Object?obj?=?iterator.next();
          ????System.out.println(obj);
          ?
          ????//?remove
          ????//?推薦,不管是遍歷還是remove都推薦
          ????iterator.remove();
          }

          lambda表達式遍歷

          list.forEach(item?->?{
          ????System.out.println(item);
          ?
          ????//?遍歷的話,推薦
          ????//?remove的話,不推薦,remove會拋
          ????//?ConcurrentModificationException異常
          });

          Stream遍歷

          list.stream().forEach(item?->?{
          ????System.out.println(item);
          ?
          ????//?遍歷的話,推薦
          ????// remove的話,不管是串行流還是并行流都不推薦,remove會拋ConcurrentModificationException異常。
          });


          對于Stream,后面我們單獨出一篇文章來了解它的原理。


          對于線程安全問題,我們的解決方案可以有:

          • 使用api之前獲取鎖,如synchronized、Lock等;

          • 使用Collections.synchronizedList();


          List的生命周期

          今天我們講解暫且告一段落了,感謝大家的閱讀。

          下一篇我們就來研究LinkedList的原理實現(xiàn)。



          -- END?--

          -??| 更多精彩文章 -



          點擊關(guān)注下方公眾號,每天學(xué) Java

          加我微信,交個朋友
          長按/掃碼添加↑↑↑

          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                    中文字幕免费观看 | 热久久视频| 免费黄色一级电影 | 成人免费视频网站 | 豆花无码视频一区二区三区四区 |