偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面試官讓我聊聊 ArrayList 解決了數(shù)組的哪些問(wèn)題

開(kāi)發(fā) 前端
在面試中經(jīng)常會(huì)問(wèn)在java中數(shù)組長(zhǎng)度和ArrayList中的size的區(qū)別?通過(guò)下面的代碼我們其實(shí)已經(jīng)看出來(lái)數(shù)組獲取其長(zhǎng)度的時(shí)候永遠(yuǎn)是在聲明的時(shí)候定義的長(zhǎng)度,即使數(shù)組中只有一個(gè)元素,通過(guò)下面的輸出有人會(huì)問(wèn)arr[1]輸出的是0,這個(gè)是因?yàn)?int 類(lèi)型在java中為基本類(lèi)型所以在初始化數(shù)組時(shí)會(huì)默認(rèn)用0填充

數(shù)組簡(jiǎn)介

數(shù)組對(duì)于我們來(lái)說(shuō)并不陌生,在內(nèi)存中是一塊連續(xù)的內(nèi)存空間,通過(guò)下標(biāo)可以隨機(jī)訪(fǎng)問(wèn)數(shù)組元素 如圖一所示,而在JDK中提供了功能更加強(qiáng)大的ArrayList其底層是基于數(shù)據(jù)實(shí)現(xiàn)的,為什么JDK已經(jīng)提供了數(shù)據(jù)還要使用ArrayList呢?我們通過(guò)比較兩者之間的差異來(lái)聊聊ArrayList的優(yōu)勢(shì)

java數(shù)組中如何獲取數(shù)組實(shí)際元素

在面試中經(jīng)常會(huì)問(wèn)在java中數(shù)組長(zhǎng)度和ArrayList中的size的區(qū)別?

通過(guò)下面的代碼我們其實(shí)已經(jīng)看出來(lái)數(shù)組獲取其長(zhǎng)度的時(shí)候永遠(yuǎn)是在聲明的時(shí)候定義的長(zhǎng)度,即使數(shù)組中只有一個(gè)元素,通過(guò)下面的輸出有人會(huì)問(wèn)arr[1]輸出的是0,這個(gè)是因?yàn)? int 類(lèi)型在java中為基本類(lèi)型所以在初始化數(shù)組時(shí)會(huì)默認(rèn)用0填充

在ArrayList中的長(zhǎng)度為list中實(shí)際元素的數(shù)量,這一點(diǎn)跟數(shù)組有著明顯的差別,具體如何實(shí)現(xiàn)后面會(huì)根據(jù)源碼分析

數(shù)組刪除元素和添加元素

在數(shù)組中刪除一個(gè)元素后需要移動(dòng)元素保證數(shù)組的連續(xù)性,如果刪除的是數(shù)組最后一個(gè)元素則不需要移動(dòng),如果刪除了下標(biāo)為3的元素后使數(shù)組連續(xù)則需要將3號(hào)元素后的元素依次向前移動(dòng)

刪除元素后下標(biāo)為7的元素不再含有有效元素,如果我們使用的數(shù)組刪除數(shù)據(jù)后這些移動(dòng)的操作需要我們寫(xiě)相關(guān)的代碼來(lái)完成,使用ArrayList刪除與數(shù)據(jù)移動(dòng)都將自動(dòng)完成不需要我們手動(dòng)處理

在數(shù)組中添加元素如果插入元素后元素個(gè)數(shù)超過(guò)了數(shù)組的長(zhǎng)度則會(huì)報(bào)數(shù)組越界的錯(cuò)誤,這是因?yàn)閿?shù)組的容量是固定的不能動(dòng)態(tài)的增加

如下圖原數(shù)組容量為8如果想要成功添加第9個(gè)元素則需要將原來(lái)數(shù)組容量擴(kuò)大為9然后移動(dòng)指定位置的元素并將9插入,正因?yàn)檫@樣數(shù)組不具有動(dòng)態(tài)性因此在使用數(shù)據(jù)時(shí)需要額外考慮很多數(shù)組本身的問(wèn)題導(dǎo)致不能專(zhuān)注于核心代碼的編寫(xiě)

ArrayList的出現(xiàn)正式解決了數(shù)組存在以下問(wèn)題

  • 動(dòng)態(tài)擴(kuò)容
  • 有效數(shù)據(jù)長(zhǎng)度
  • 增加刪除元素后數(shù)據(jù)移動(dòng)
  • 數(shù)據(jù)遍歷

結(jié)合ArrayList一些面試問(wèn)題來(lái)看下具體源代碼

  • ArrayList的默認(rèn)初始化容量
  • 何時(shí)擴(kuò)容
  • 擴(kuò)容容量大小
  • 遍歷刪除fast fail原理
  • 迭代器刪除為什么不越界

首先看下ArrayList的兩個(gè)重要的屬性

  • elementData 存儲(chǔ)數(shù)據(jù)的數(shù)組
  • size 數(shù)組中實(shí)際元素個(gè)數(shù)
  1. transient Object[] elementData; // non-private to simplify nested class access 
  2.  /** 
  3.   * The size of the ArrayList (the number of elements it contains). 
  4.   * 
  5.   * @serial 
  6.   */ 
  7.  private int size

ArrayList 的構(gòu)造函數(shù)分為有參和無(wú)參兩種方式

  • 無(wú)參構(gòu)造函數(shù)為ArrayList()其初始化后并未分配內(nèi)存空間而是在第一次add操作時(shí)分配
  • 有參構(gòu)造函數(shù)ArrayList(int initialCapacity)初始化即分配制定大小內(nèi)存
  • 有參構(gòu)造函數(shù)ArrayList(Collection c) 初始化即分配內(nèi)存

問(wèn)題一: 無(wú)參初始化默認(rèn)容量是多少,何時(shí)擴(kuò)容,擴(kuò)容大小為多少都在下面的注釋中可以找到

具體分析請(qǐng)看下面注釋

  1. // 默認(rèn)初始化elementData為空數(shù)組 
  2. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 
  3. public ArrayList() { 
  4.     this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 
  5. //接下來(lái)進(jìn)行add操作 
  6. public boolean add(E e) { 
  7.     // 檢查當(dāng)前數(shù)據(jù)容量是否充足 
  8.     ensureCapacityInternal(size + 1);  // Increments modCount!! 
  9.     // size 自增可以保證有效元素的個(gè)數(shù) 
  10.     elementData[size++] = e; 
  11.     return true
  12.  } 
  13. //計(jì)算容量大小主要用于默認(rèn)初始化第一次add操作 
  14. private static int calculateCapacity(Object[] elementData, int minCapacity) { 
  15.     //默認(rèn)初始化時(shí)elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA 
  16.     // 此處返回默認(rèn)容量DEFAULT_CAPACITY,此值大小為10 
  17.     if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 
  18.         return Math.max(DEFAULT_CAPACITY, minCapacity); 
  19.      } 
  20.     return minCapacity; 
  21. private void ensureCapacityInternal(int minCapacity) { 
  22.      ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); 
  23. private void ensureExplicitCapacity(int minCapacity) { 
  24.      modCount++; 
  25.     //檢查是否擴(kuò)容,如果當(dāng)前容量大于數(shù)組長(zhǎng)度進(jìn)行擴(kuò)容 
  26.     // overflow-conscious code 
  27.      if (minCapacity - elementData.length > 0) 
  28.         grow(minCapacity); 
  29. //根據(jù)原來(lái)數(shù)據(jù)長(zhǎng)度進(jìn)行擴(kuò)容 
  30. //oldCapacity >> 1 位運(yùn)算相當(dāng)于 oldCapacity=oldCapacity/2 
  31. //新容量為 newCapacity = oldCapacity + (oldCapacity >> 1);即為原來(lái)的1.5倍 
  32. //將老數(shù)組中的數(shù)據(jù)移動(dòng)到新數(shù)組中 
  33. //此處解釋下為何為1.5倍,這是一種折中是對(duì)擴(kuò)容次數(shù)和空間大小的折中,如果擴(kuò)容次數(shù)太多會(huì)降低效率如果空間太大會(huì)浪費(fèi)空間 
  34. private void grow(int minCapacity) { 
  35.    // overflow-conscious code 
  36.    int oldCapacity = elementData.length; 
  37.    int newCapacity = oldCapacity + (oldCapacity >> 1); 
  38.    if (newCapacity - minCapacity < 0) 
  39.       newCapacity = minCapacity; 
  40.    if (newCapacity - MAX_ARRAY_SIZE > 0) 
  41.       newCapacity = hugeCapacity(minCapacity); 
  42.       // minCapacity is usually close to size, so this is a win: 
  43.       elementData = Arrays.copyOf(elementData, newCapacity); 

問(wèn)題二:數(shù)據(jù)遍歷,fast-fail,迭代器刪除為什么不越界

在如下代碼注釋中將找到答案

  • ArrayList 遍歷支持for,foreach,迭代器遍歷
  • fail-fast 機(jī)制是java集合(Collection)中的一種錯(cuò)誤機(jī)制。當(dāng)多個(gè)線(xiàn)程對(duì)同一個(gè)集合的內(nèi)容進(jìn)行操作時(shí),就可能會(huì)產(chǎn)生fail-fast事件。

例如:當(dāng)某一個(gè)線(xiàn)程A通過(guò)iterator去遍歷某集合的過(guò)程中,若該集合的內(nèi)容被其他線(xiàn)程所改變了;那么線(xiàn)程A訪(fǎng)問(wèn)集合時(shí),就會(huì)拋出ConcurrentModificationException異常,產(chǎn)生fail-fast事件。

  1. //ArrayList 迭代器是通過(guò)兩個(gè)游標(biāo)數(shù)組的下標(biāo) 
  2.  private class Itr implements Iterator<E> {         // 代表下一個(gè)元素的游標(biāo) 
  3.         int cursor;       // index of next element to return 
  4.         int lastRet = -1; // index of last element returned; -1 if no such 
  5.         int expectedModCount = modCount; 
  6.         Itr() {}        // 如果游標(biāo)不等于size 代表還有下一個(gè)元素        public boolean hasNext() {            return cursor != size
  7.         }       //        @SuppressWarnings("unchecked"
  8.         public E next() { 
  9.             checkForComodification();            int i = cursor
  10.             // 在此處判斷當(dāng)前游標(biāo)是超過(guò)了數(shù)組有效元素個(gè)數(shù) 
  11.             if (i >= size
  12.                 throw new NoSuchElementException();            Object[] elementData = ArrayList.this.elementData;            //檢查是否數(shù)組越界 
  13.             if (i >= elementData.length) 
  14.                 throw new ConcurrentModificationException();            cursor = i + 1; 
  15.             // 更新lastRet游標(biāo)為當(dāng)前數(shù)組下標(biāo) 
  16.             return (E) elementData[lastRet = i]; 
  17.         }        public void remove() {         // 檢查刪除元素下標(biāo)是否合法 
  18.             if (lastRet < 0) 
  19.                 throw new IllegalStateException();            checkForComodification();            try {            // 刪除原數(shù)組中制定下標(biāo)元素 
  20.                 ArrayList.this.remove(lastRet);                //更新游標(biāo) 
  21.                 cursor = lastRet;                lastRet = -1; 
  22.                 expectedModCount = modCount;            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }       } 

 

責(zé)任編輯:未麗燕 來(lái)源: 今日頭條
相關(guān)推薦

2022-05-23 08:43:02

BigIntJavaScript內(nèi)置對(duì)象

2019-04-29 14:59:41

Tomcat系統(tǒng)架構(gòu)

2023-01-17 17:54:47

MQ數(shù)據(jù)丟失

2025-03-10 08:00:05

2024-11-14 14:53:04

2021-07-13 07:52:03

ReactHooks組件

2020-05-22 08:11:48

線(xiàn)程池JVM面試

2021-09-28 13:42:55

Chrome Devwebsocket網(wǎng)絡(luò)協(xié)議

2021-07-29 07:55:20

React Fiber架構(gòu)引擎

2021-12-02 08:19:06

MVCC面試數(shù)據(jù)庫(kù)

2022-04-10 18:10:24

CURD鏈表

2023-02-20 08:08:48

限流算法計(jì)數(shù)器算法令牌桶算法

2025-03-11 09:19:53

2020-09-08 06:43:53

B+樹(shù)面試索引

2022-11-15 17:45:46

數(shù)據(jù)庫(kù)MySQL

2020-07-02 07:52:11

RedisHash映射

2021-05-28 07:12:58

Mybatis面試官Java

2024-07-25 18:20:03

2021-03-01 18:42:02

緩存LRU算法

2019-08-23 09:20:35

Spring 5編程Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)