面經手冊 · 第7篇《ArrayList也這麼多知識?一個指定位置插入就把謝飛機面暈了!》

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:小傅哥"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"博客:"},{"type":"link","attrs":{"href":"https://bugstack.cn","title":""},"content":[{"type":"text","text":"https://bugstack.cn"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"沉澱、分享、成長,讓自己和他人都能有所收穫!😄"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"一、前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"數據結構是寫好代碼的基礎!"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"說到數據結構基本包括;數組、鏈表、隊列、紅黑樹等,但當你看到這些數據結構以及想到自己平時的開發,似乎並沒有用到過。那麼爲什麼還要學習數據結構?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實這些知識點你並不是沒有用到的,而是Java中的API已經將各個數據結構封裝成對應的工具類,例如ArrayList、LinkedList、HashMap等,就像在前面的章節中,小傅哥寫了5篇文章將近2萬字來分析HashMap,從而學習它的核心設計邏輯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可能有人覺得這類知識就像"},{"type":"text","marks":[{"type":"strong"}],"text":"八股文"},{"type":"text","text":",學習只是爲了應付面試。如果你真的把這些用於支撐其整個語言的根基當八股文學習,那麼硬背下來不會有多少收穫。理科學習更在乎邏輯,重在是理解基本原理,有了原理基礎就複用這樣的技術運用到實際的業務開發。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那麼,你什麼時候會用到這樣的技術呢?就是,當你考慮體量、夯實服務、琢磨性能時,就會逐漸的深入到數據結構以及核心的基本原理當中,那裏的每一分深入,都會讓整個服務性能成指數的提升。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"二、面試題"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"謝飛機"},{"type":"text","text":",聽說你最近在家很努力學習HashMap?那考你個ArrayList知識點🦀"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你看下面這段代碼輸出結果是什麼?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public static void main(String[] args) {\n List list = new ArrayList(10);\n list.add(2, \"1\");\n System.out.println(list.get(0));\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"嗯?不知道!👀眼睛看題,看我臉幹啥?好好好,告訴你吧,這樣會報錯!至於爲什麼,回家看看書吧。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"Exception in thread \"main\" java.lang.IndexOutOfBoundsException: Index: 2, Size: 0\n\tat java.util.ArrayList.rangeCheckForAdd(ArrayList.java:665)\n\tat java.util.ArrayList.add(ArrayList.java:477)\n\tat org.itstack.interview.test.ApiTest.main(ApiTest.java:13)\n\nProcess finished with exit code 1"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"🤭謝飛機是懵了,咱們一點點分析ArrayList"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"三、數據結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Array + List = 數組 + 列表 = ArrayList = 數組列表"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/61/6179787ad946dff605454a2640a3f00f.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ArrayList的數據結構是基於數組實現的,只不過這個數組不像我們普通定義的數組,它可以在ArrayList的管理下插入數據時按需動態擴容、數據拷貝等操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來,我們就逐步分析ArrayList的源碼,也同時解答"},{"type":"codeinline","content":[{"type":"text","text":"謝飛機"}]},{"type":"text","text":"的疑問。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"四、源碼分析"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1. 初始化"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"List list = new ArrayList(10);\n\npublic ArrayList() {\n this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;\n}\n\n /**\n * Constructs an empty list with the specified initial capacity.\n *\n * @param initialCapacity the initial capacity of the list\n * @throws IllegalArgumentException if the specified initial capacity\n * is negative\n */\n public ArrayList(int initialCapacity) {\n if (initialCapacity > 0) {\n this.elementData = new Object[initialCapacity];\n } else if (initialCapacity == 0) {\n this.elementData = EMPTY_ELEMENTDATA;\n } else {\n throw new IllegalArgumentException(\"Illegal Capacity: \"+\n initialCapacity);\n }\n }"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通常情況空構造函數初始化ArrayList更常用,這種方式數組的長度會在第一次插入數據時候進行設置。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當我們已經知道要填充多少個元素到ArrayList中,比如500個、1000個,那麼爲了提供性能,減少ArrayList中的拷貝操作,這個時候會直接初始化一個預先設定好的長度。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"另外,"},{"type":"codeinline","content":[{"type":"text","text":"EMPTY_ELEMENTDATA"}]},{"type":"text","text":" 是一個定義好的空對象;"},{"type":"codeinline","content":[{"type":"text","text":"private static final Object[] EMPTY_ELEMENTDATA = {}"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.1 方式01;普通方式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"ArrayList list = new ArrayList();\nlist.add(\"aaa\");\nlist.add(\"bbb\");\nlist.add(\"ccc\");"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個方式很簡單也是我們最常用的方式。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.2 方式02;內部類方式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"ArrayList list = new ArrayList() \\\\{\n add(\"aaa\");\n add(\"bbb\");\n add(\"ccc\");\n\\\\};"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種方式也是比較常用的,而且省去了多餘的代碼量。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.3 方式03;Arrays.asList"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":" ArrayList list = new ArrayList(Arrays.asList(\"aaa\", \"bbb\", \"ccc\"));"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上是通過"},{"type":"codeinline","content":[{"type":"text","text":"Arrays.asList"}]},{"type":"text","text":"傳遞給"},{"type":"codeinline","content":[{"type":"text","text":"ArrayList"}]},{"type":"text","text":"構造函數的方式進行初始化,這裏有幾個知識點;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"1.3.1 ArrayList構造函數"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public ArrayList(Collection extends E> c) {\n elementData = c.toArray();\n if ((size = elementData.length) != 0) {\n // c.toArray might (incorrectly) not return Object[] (see 6260652)\n if (elementData.getClass() != Object[].class)\n elementData = Arrays.copyOf(elementData, size, Object[].class);\n } else {\n // replace with empty array.\n this.elementData = EMPTY_ELEMENTDATA;\n }\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過構造函數可以看到,只要實現"},{"type":"codeinline","content":[{"type":"text","text":"Collection"}]},{"type":"text","text":"類的都可以作爲入參。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在通過轉爲數組以及拷貝"},{"type":"codeinline","content":[{"type":"text","text":"Arrays.copyOf"}]},{"type":"text","text":"到"},{"type":"codeinline","content":[{"type":"text","text":"Object[]"}]},{"type":"text","text":"集合中在賦值給屬性"},{"type":"codeinline","content":[{"type":"text","text":"elementData"}]},{"type":"text","text":"。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"**注意:c.toArray might (incorrectly) not return Object[] ("},{"type":"codeinline","content":[{"type":"text","text":"see 6260652"}]},{"type":"text","text":")**"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"see 6260652 是JDK bug庫的編號,有點像商品sku,bug地址:"},{"type":"link","attrs":{"href":"https://bugs.java.com/bugdatabase/viewbug.do?bugid=6260652","title":""},"content":[{"type":"text","text":"https://bugs.java.com/bugdatabase/view"},{"type":"text","marks":[{"type":"italic"}],"text":"bug.do?bug"},{"type":"text","text":"id=6260652"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那這是個什麼bug呢,我們來測試下面這段代碼;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Test\npublic void t(){\n List list1 = Arrays.asList(1, 2, 3);\n System.out.println(\"通過數組轉換:\" + (list1.toArray().getClass() == Object[].class));\n \n ArrayList list2 = new ArrayList(Arrays.asList(1, 2, 3));\n System.out.println(\"通過集合轉換:\" + (list2.toArray().getClass() == Object[].class));\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"測試結果:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"通過數組轉換:false\n通過集合轉換:true\n\nProcess finished with exit code 0"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"public Object[] toArray()"}]},{"type":"text","text":" 返回的類型不一定就是 "},{"type":"codeinline","content":[{"type":"text","text":"Object[]"}]},{"type":"text","text":",其類型取決於其返回的實際類型,畢竟 Object 是父類,它可以是其他任意類型。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"子類實現和父類同名的方法,僅僅返回值不一致時,默認調用的是子類的實現方法。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"造成這個結果的原因,如下;"}]},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Arrays.asList 使用的是:"},{"type":"codeinline","content":[{"type":"text","text":"Arrays.copyOf(this.a, size,(Class extends T[]>) a.getClass());"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"ArrayList 構造函數使用的是:"},{"type":"codeinline","content":[{"type":"text","text":"Arrays.copyOf(elementData, size, Object[].class);"}]},{"type":"text","text":" "}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"1.3.2 Arrays.asList"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"你知道嗎?"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Arrays.asList 構建的集合,不能賦值給 ArrayList"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Arrays.asList 構建的集合,不能再添加元素"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Arrays.asList 構建的集合,不能再刪除元素"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那這到底爲什麼呢,因爲Arrays.asList構建出來的List與new ArrayList得到的List,壓根就不是一個List!類關係圖如下;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5d/5d704546a9cc398ad471b1e9e3061dee.png","alt":"小傅哥 bugstack.cn & List類關係圖","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從以上的類圖關係可以看到;"}]},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"這兩個List壓根不同一個東西,而且Arrasys下的List是一個私有類,只能通過asList使用,不能單獨創建。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"另外還有這個ArrayList不能添加和刪除,主要是因爲它的實現方式,可以參考Arrays類中,這部分源碼;"},{"type":"codeinline","content":[{"type":"text","text":"private static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"*此外,Arrays是一個工具包,裏面還有一些非常好用的方法,例如;二分查找"},{"type":"codeinline","content":[{"type":"text","text":"Arrays.binarySearch"}]},{"type":"text","text":"、排序"},{"type":"codeinline","content":[{"type":"text","text":"Arrays.sort"}]},{"type":"text","text":"等*"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"1.4 方式04;Collections.ncopies"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Collections.nCopies"}]},{"type":"text","text":" 是集合方法中用於生成多少份某個指定元素的方法,接下來就用它來初始化ArrayList,如下;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"ArrayList list = new ArrayList(Collections.nCopies(10, 0));"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這會初始化一個由10個0組成的集合。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2. 插入"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ArrayList對元素的插入,其實就是對數組的操作,只不過需要特定時候擴容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.1 普通插入"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"List list = new ArrayList();\nlist.add(\"aaa\");\nlist.add(\"bbb\");\nlist.add(\"ccc\");"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當我們依次插入添加元素時,ArrayList.add方法只是把元素記錄到數組的各個位置上了,源碼如下;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"/**\n * Appends the specified element to the end of this list.\n *\n * @param e element to be appended to this list\n * @return true (as specified by {@link Collection#add})\n */\npublic boolean add(E e) {\n ensureCapacityInternal(size + 1); // Increments modCount!!\n elementData[size++] = e;\n return true;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是插入元素時候的源碼,"},{"type":"codeinline","content":[{"type":"text","text":"size++"}]},{"type":"text","text":"自增,把對應元素添加進去。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.2 插入時擴容"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在前面"},{"type":"codeinline","content":[{"type":"text","text":"初始化"}]},{"type":"text","text":"部分講到,ArrayList默認初始化時會申請10個長度的空間,如果超過這個長度則需要進行擴容,那麼它是怎麼擴容的呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從根本上分析來說,數組是定長的,如果超過原來定長長度,擴容則需要申請新的數組長度,並把原數組元素拷貝到新數組中,如下圖;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b2/b2d444c64aae73a9f87fb6e56d5d5f19.png","alt":"小傅哥 bugstack.cn & 數組擴容","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"圖中介紹了當List結合可用空間長度不足時則需要擴容,這主要包括如下步驟;"}]},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"判斷長度充足;"},{"type":"codeinline","content":[{"type":"text","text":"ensureCapacityInternal(size + 1);"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"當判斷長度不足時,則通過擴大函數,進行擴容;"},{"type":"codeinline","content":[{"type":"text","text":"grow(int minCapacity)"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"擴容的長度計算;"},{"type":"codeinline","content":[{"type":"text","text":"int newCapacity = oldCapacity + (oldCapacity >> 1);"}]},{"type":"text","text":",舊容量 + 舊容量右移1位,這相當於擴容了原來容量的"},{"type":"codeinline","content":[{"type":"text","text":"(int)3/2"}]},{"type":"text","text":"。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 4. \t10,擴容時:1010 + 1010 >> 1 = 1010 + 0101 = 10 + 5 = 15"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 2. 7,擴容時:0111 + 0111 >> 1 = 0111 + 0011 = 7 + 3 = 10"}]},{"type":"numberedlist","attrs":{"start":"4","normalizeStart":"4"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"當擴容完以後,就需要進行把數組中的數據拷貝到新數組中,這個過程會用到"},{"type":"codeinline","content":[{"type":"text","text":" Arrays.copyOf(elementData, newCapacity);"}]},{"type":"text","text":",但他的底層用到的是;"},{"type":"codeinline","content":[{"type":"text","text":"System.arraycopy"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"System.arraycopy;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Test\npublic void test_arraycopy() {\n int[] oldArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int[] newArr = new int[oldArr.length + (oldArr.length >> 1)];\n System.arraycopy(oldArr, 0, newArr, 0, oldArr.length);\n \n newArr[11] = 11;\n newArr[12] = 12;\n newArr[13] = 13;\n newArr[14] = 14;\n \n System.out.println(\"數組元素:\" + JSON.toJSONString(newArr));\n System.out.println(\"數組長度:\" + newArr.length);\n \n /**\n * 測試結果\n * \n * 數組元素:[1,2,3,4,5,6,7,8,9,10,0,11,12,13,14]\n * 數組長度:15\n */\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"拷貝數組的過程並不複雜,主要是對"},{"type":"codeinline","content":[{"type":"text","text":"System.arraycopy"}]},{"type":"text","text":"的操作。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面就是把數組"},{"type":"codeinline","content":[{"type":"text","text":"oldArr"}]},{"type":"text","text":"拷貝到"},{"type":"codeinline","content":[{"type":"text","text":"newArr"}]},{"type":"text","text":",同時新數組的長度,採用和ArrayList一樣的計算邏輯;"},{"type":"codeinline","content":[{"type":"text","text":"oldArr.length + (oldArr.length >> 1)"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.3 指定位置插入"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"list.add(2, \"1\");"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到這,終於可以說說"},{"type":"codeinline","content":[{"type":"text","text":"謝飛機"}]},{"type":"text","text":"的面試題,這段代碼輸出結果是什麼,如下;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"Exception in thread \"main\" java.lang.IndexOutOfBoundsException: Index: 2, Size: 0\n\tat java.util.ArrayList.rangeCheckForAdd(ArrayList.java:665)\n\tat java.util.ArrayList.add(ArrayList.java:477)\n\tat org.itstack.interview.test.ApiTest.main(ApiTest.java:14)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"其實"},{"type":"text","text":",一段報錯提示,爲什麼呢?我們翻開下源碼學習下。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.3.1 容量驗證"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public void add(int index, E element) {\n rangeCheckForAdd(index);\n \n ...\n}\n\nprivate void rangeCheckForAdd(int index) {\n if (index > size || index < 0)\n throw new IndexOutOfBoundsException(outOfBoundsMsg(index));\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"指定位置插入首先要判斷"},{"type":"codeinline","content":[{"type":"text","text":"rangeCheckForAdd"}]},{"type":"text","text":",size的長度。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過上面的元素插入我們知道,每插入一個元素,size自增一次"},{"type":"codeinline","content":[{"type":"text","text":"size++"}]},{"type":"text","text":"。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以即使我們申請了10個容量長度的ArrayList,但是指定位置插入會依賴於size進行判斷,所以會拋出"},{"type":"codeinline","content":[{"type":"text","text":"IndexOutOfBoundsException"}]},{"type":"text","text":"異常。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"2.3.2 元素遷移"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/76/76b6725869605d3c5be927f9ebdd90ca.png","alt":"小傅哥 bugstack.cn & 插入元素遷移","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"指定位置插入的核心步驟包括;"}]},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"判斷size,是否可以插入。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"判斷插入後是否需要擴容;"},{"type":"codeinline","content":[{"type":"text","text":"ensureCapacityInternal(size + 1);"}]},{"type":"text","text":"。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"數據元素遷移,把從待插入位置後的元素,順序往後遷移。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"給數組的指定位置賦值,也就是把待插入元素插入進來。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"部分源碼:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public void add(int index, E element) {\n\t...\n\t// 判斷是否需要擴容以及擴容操作\n\tensureCapacityInternal(size + 1);\n // 數據拷貝遷移,把待插入位置空出來\n System.arraycopy(elementData, index, elementData, index + 1,\n size - index);\n // 數據插入操作 \n elementData[index] = element;\n size++;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這部分源碼的主要核心是在,"},{"type":"codeinline","content":[{"type":"text","text":"System.arraycopy"}]},{"type":"text","text":",上面我們已經演示過相應的操作方式。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏只是設定了指定位置的遷移,可以把上面的案例代碼複製下來做測試驗證。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"實踐:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"List list = new ArrayList(Collections.nCopies(9, \"a\"));\nSystem.out.println(\"初始化:\" + list);\n\nlist.add(2, \"b\");\nSystem.out.println(\"插入後:\" + list);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"測試結果:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"初始化:[a, a, a, a, a, a, a, a, a]\n插入後:[a, a, 1, a, a, a, a, a, a, a]\n\nProcess finished with exit code 0"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"指定位置已經插入元素"},{"type":"codeinline","content":[{"type":"text","text":"1"}]},{"type":"text","text":",後面的數據向後遷移完成。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3. 刪除"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了指定位置插入元素的經驗,理解刪除的過長就比較容易了,如下圖;"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/be/befd4fd4aa9e7dd71a50e9b441669b56.png","alt":"小傅哥 bugstack.cn & 刪除元素","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏我們結合着代碼:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public E remove(int index) {\n rangeCheck(index);\n modCount++;\n E oldValue = elementData(index);\n int numMoved = size - index - 1;\n if (numMoved > 0)\n System.arraycopy(elementData, index+1, elementData, index,\n numMoved);\n elementData[--size] = null; // clear to let GC do its work\n return oldValue;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"刪除的過程主要包括;"}]},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"校驗是否越界;"},{"type":"codeinline","content":[{"type":"text","text":"rangeCheck(index);"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"計算刪除元素的移動長度"},{"type":"codeinline","content":[{"type":"text","text":"numMoved"}]},{"type":"text","text":",並通過"},{"type":"codeinline","content":[{"type":"text","text":"System.arraycopy"}]},{"type":"text","text":"自己把元素複製給自己。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"把結尾元素清空,null。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"這裏我們做個例子:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Test\npublic void test_copy_remove() {\n int[] oldArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\n int index = 2;\n int numMoved = 10 - index - 1;\n System.arraycopy(oldArr, index + 1, oldArr, index, numMoved);\n System.out.println(\"數組元素:\" + JSON.toJSONString(oldArr));\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"設定一個擁有10個元素的數組,同樣按照ArrayList的規則進行移動元素。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意,爲了方便觀察結果,這裏沒有把結尾元素設置爲null。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"測試結果:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"數組元素:[1,2,4,5,6,7,8,9,10,10]\n\nProcess finished with exit code 0"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到指定位置 index = 2,元素已經被刪掉。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同時數組已經移動用"},{"type":"codeinline","content":[{"type":"text","text":"元素4"}]},{"type":"text","text":"佔據了原來"},{"type":"codeinline","content":[{"type":"text","text":"元素3"}]},{"type":"text","text":"的位置,同時結尾的10還等待刪除。"},{"type":"text","marks":[{"type":"italic"}],"text":"這就是爲什麼ArrayList中有這麼一句代碼;elementData[--size] = null"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4. 擴展"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果給你一組元素;"},{"type":"codeinline","content":[{"type":"text","text":"a、b、c、d、e、f、g"}]},{"type":"text","text":",需要你放到ArrayList中,但是要求獲取一個元素的時間複雜度都是O(1),你怎麼處理?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"想解決這個問題,就需要知道元素添加到集合中後知道它的位置,而這個位置呢,其實可以通過哈希值與集合長度與運算,得出存放數據的下標,如下圖;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/28/28c1f91fb3c2a12f7df2e87704ba471f.png","alt":"小傅哥 bugstack.cn & 下標計算","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如圖就是計算出每一個元素應該存放的位置,這樣就可以O(1)複雜度獲取元素。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4.1 代碼操作(添加元素)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"List list = new ArrayList(Collections.nCopies(8, \"0\"));\n\nlist.set(\"a\".hashCode() & 8 - 1, \"a\");\nlist.set(\"b\".hashCode() & 8 - 1, \"b\");\nlist.set(\"c\".hashCode() & 8 - 1, \"c\");\nlist.set(\"d\".hashCode() & 8 - 1, \"d\");\nlist.set(\"e\".hashCode() & 8 - 1, \"e\");\nlist.set(\"f\".hashCode() & 8 - 1, \"f\");\nlist.set(\"g\".hashCode() & 8 - 1, \"g\");"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上是初始化"},{"type":"codeinline","content":[{"type":"text","text":"ArrayList"}]},{"type":"text","text":",並存放相應的元素。存放時候計算出每個元素的下標值。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4.2 代碼操作(獲取元素)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"System.out.println(\"元素集合:\" + list);\nSystem.out.println(\"獲取元素f [\\\"f\\\".hashCode() & 8 - 1)] Idx:\" + (\"f\".hashCode() & (8 - 1)) + \" 元素:\" + list.get(\"f\".hashCode() & 8 - 1));\nSystem.out.println(\"獲取元素e [\\\"e\\\".hashCode() & 8 - 1)] Idx:\" + (\"e\".hashCode() & (8 - 1)) + \" 元素:\" + list.get(\"e\".hashCode() & 8 - 1));\nSystem.out.println(\"獲取元素d [\\\"d\\\".hashCode() & 8 - 1)] Idx:\" + (\"d\".hashCode() & (8 - 1)) + \" 元素:\" + list.get(\"d\".hashCode() & 8 - 1));"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"4.3 測試結果"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"元素集合:[0, a, b, c, d, e, f, g]\n\n獲取元素f [\"f\".hashCode() & 8 - 1)] Idx:6 元素:f\n獲取元素e [\"e\".hashCode() & 8 - 1)] Idx:5 元素:e\n獲取元素d [\"d\".hashCode() & 8 - 1)] Idx:4 元素:d\n\nProcess finished with exit code 0"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過測試結果可以看到,下標位置0是初始元素,元素是按照指定的下標進行插入的。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那麼現在獲取元素的時間複雜度就是O(1),是不有點像"},{"type":"codeinline","content":[{"type":"text","text":"HashMap"}]},{"type":"text","text":"中的桶結構。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"五、總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"就像我們開頭說的一樣,數據結構是你寫出代碼的基礎,更是寫出高級代碼的核心。只有瞭解好數據結構,才能更透徹的理解程序設計。"},{"type":"text","marks":[{"type":"italic"}],"text":"並不是所有的邏輯都是for循環"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"面試題只是引導你學習的點,但不能爲了面試題而忽略更重要的核心知識學習,背一兩道題是不可能抗住深度問的。因爲任何一個考點,都不只是一種問法,往往可以從很多方面進行提問和考查。就像你看完整篇文章,是否理解了沒有說到的知識,當你固定位置插入數據時會進行數據遷移,那麼在擁有大量數據的ArrayList中是不適合這麼做的,非常影響性能。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在本章的內容編寫的時候也參考到一些優秀的資料,尤其發現這份外文文檔;"},{"type":"link","attrs":{"href":"https://beginnersbook.com/","title":""},"content":[{"type":"text","text":"https://beginnersbook.com/"}]},{"type":"text","text":" 大家可以參考學習。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"六、系列文章"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://bugstack.cn/interview/2020/08/07/%E9%9D%A2%E7%BB%8F%E6%89%8B%E5%86%8C-%E7%AC%AC3%E7%AF%87-HashMap%E6%A0%B8%E5%BF%83%E7%9F%A5%E8%AF%86-%E6%89%B0%E5%8A%A8%E5%87%BD%E6%95%B0-%E8%B4%9F%E8%BD%BD%E5%9B%A0%E5%AD%90-%E6%89%A9%E5%AE%B9%E9%93%BE%E8%A1%A8%E6%8B%86%E5%88%86-%E6%B7%B1%E5%BA%A6%E5%AD%A6%E","title":""},"content":[{"type":"text","text":"HashMap核心知識,擾動函數、負載因子、擴容鏈表拆分,深度學習"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://bugstack.cn/itstack-code-life/2020/04/11/%E5%B7%A5%E4%BD%9C%E4%B8%A4%E5%B9%B4%E7%AE%80%E5%8E%86%E5%86%99%E6%88%90%E8%BF%99%E6%A0%B7-%E8%B0%81%E8%A6%81%E4%BD%A0%E5%91%80.html","title":""},"content":[{"type":"text","text":"簡歷寫成這樣,誰要你呀!"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://bugstack.cn/itstack-code-life/2020/03/31/%E5%A4%A7%E5%AD%A6%E5%9B%9B%E5%B9%B4%E5%88%B0%E6%AF%95%E4%B8%9A%E5%B7%A5%E4%BD%9C5%E5%B9%B4%E7%9A%84%E5%AD%A6%E4%B9%A0%E8%B7%AF%E7%BA%BF%E8%B5%84%E6%BA%90%E6%B1%87%E6%80%BB.html","title":""},"content":[{"type":"text","text":"工作5年的學習路線資源彙總"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://bugstack.cn/itstack-code-life/2020/04/30/%E8%AE%B2%E9%81%93%E7%90%86-%E5%8F%AA%E8%A6%81%E4%BD%A0%E6%98%AF%E4%B8%80%E4%B8%AA%E7%88%B1%E6%8A%98%E8%85%BE%E7%9A%84%E7%A8%8B%E5%BA%8F%E5%91%98-%E6%AF%95%E4%B8%9A%E6%89%BE%E5%B7%A5%E4%BD%9C%E7%9C%9F%E7%9A%84%E4%B8%8D%E9%9C%80%E8%A6%81%E5%86%8D%E8%8A","title":""},"content":[{"type":"text","text":"講道理,只要你是一個愛折騰的程序員,畢業找工作真的不需要再花錢培訓!"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://bugstack.cn/itstack-code-life/2020/07/25/12%E5%A4%A9-%E8%BF%99%E6%9C%AC-%E9%87%8D%E5%AD%A6Java%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-PDF%E4%B9%A6%E7%B1%8D%E4%B8%8B%E8%BD%BD%E9%87%8F9k-%E6%96%B0%E5%A2%9E%E7%B2%89%E4%B8%9D1400%E4%BA%BA-Github%E4%B8%8A%E5%85%A8%E7%90%83%E6%8E%A8%E8%8D%90%E6%A6%9C","title":""},"content":[{"type":"text","text":"高級開發必須要懂設計模式,並能重構代碼"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章