摘要:二數(shù)組擴(kuò)容及拷貝數(shù)組的擴(kuò)容數(shù)組是根據(jù)固定容量創(chuàng)建的,在必要的時(shí)候我們需要對(duì)數(shù)組進(jìn)行擴(kuò)容初始長度為下面決定需要對(duì)數(shù)組進(jìn)行擴(kuò)容對(duì)原數(shù)組進(jìn)行內(nèi)容拷貝在對(duì)數(shù)組進(jìn)行拷貝時(shí)除了利用循環(huán)遍歷數(shù)組元素進(jìn)行拷貝外,推薦使用更高效的方法。
PS:如果覺得文章有什么地方寫錯(cuò)了,哪里寫得不好,或者有什么建議,歡迎指點(diǎn)。一、認(rèn)識(shí)數(shù)組
數(shù)組是一種線性表數(shù)據(jù)結(jié)構(gòu)。它用一塊連續(xù)的內(nèi)存空間,來存儲(chǔ)相同類型的一組數(shù)據(jù)。
1. 概念的理解 線性表:顧名思義,線性表就是數(shù)據(jù)排列成像一條線一樣的結(jié)構(gòu)。每個(gè)線性表上的數(shù)據(jù)最多只有前和后兩個(gè)方向,數(shù)組,鏈表,棧,隊(duì)列等都是典型的線性表結(jié)構(gòu)。
與其相對(duì)立的,在非線性表中,數(shù)據(jù)之間并不是簡單的前后關(guān)系,像樹,堆,圖等都是典型的非線性表。
連續(xù)的內(nèi)存空間和相同類型的數(shù)據(jù):即計(jì)算機(jī)分配連續(xù)的內(nèi)存單元來存儲(chǔ)數(shù)據(jù),相同類型的數(shù)據(jù)即每個(gè)內(nèi)存單元的大小是相同的。
如聲明一個(gè)長度為 5 的 int 類型的數(shù)組 int[] arr = new int[5] ,計(jì)算機(jī)給數(shù)組分配了一塊連續(xù)的內(nèi)存空間,其中內(nèi)存塊的首地址為 base_address = 0xc0000160e0,每個(gè)內(nèi)存單元占 4 個(gè)字節(jié):
2. 高效的隨機(jī)訪問數(shù)組的一個(gè)特點(diǎn)是可以根據(jù)下標(biāo)隨機(jī)訪問數(shù)組元素,其時(shí)間復(fù)雜度為 O(1),那么它是如何實(shí)現(xiàn)的呢?
計(jì)算機(jī)分配的內(nèi)存單元存儲(chǔ)數(shù)據(jù)時(shí),也會(huì)為內(nèi)存單元分配一個(gè)地址,然后可以通過地址來訪問內(nèi)存中的數(shù)據(jù)。由數(shù)組的內(nèi)存空間連續(xù)的特性,當(dāng)需要訪問某個(gè)元素時(shí),它會(huì)通過下面的尋址公式來計(jì)算出該元素存儲(chǔ)的內(nèi)存地址:
// 一維數(shù)組 arr[n]: arr[i]_address = base_address + i * data_type_size // 二維數(shù)組 arr[m][n]: address = base_address + (i * n + j) * data_type_size
其中 data_type_size 表示數(shù)組中每個(gè)元素的大小,如在 int 型的數(shù)組 arr 中,data_type_size 就為 4 個(gè)字節(jié)。
這樣,便可以很快的根據(jù)內(nèi)存地址來讀取數(shù)據(jù)。
3. 低效的“插入”和“刪除”在數(shù)組中,為了保持內(nèi)存數(shù)據(jù)的連續(xù)性,會(huì)導(dǎo)致插入、刪除這兩個(gè)操作比較低效。
例如在 插入操作 中,假設(shè)數(shù)組的長度為 n,若我們要在數(shù)組的第 k 個(gè)位置插入一個(gè)數(shù)據(jù),為了把第 k 個(gè)位置騰出來給新的數(shù)據(jù),我們需要將第 k ~ n 這部分的元素都順序地向后挪一位: arr[i] = arr[i-1] 。其時(shí)間復(fù)雜度為 O(n)。
而在 刪除操作 中,若我們要?jiǎng)h除數(shù)組的第 k 個(gè)元素,為了內(nèi)存的連續(xù)性,就需要將第 k ~ n 這部分的元素都順序地向前挪一位: arr[i] = arr[i+1] 。其時(shí)間復(fù)雜度為 O(n)。
插入和刪除操作的優(yōu)化然而在很多我們不需要考慮數(shù)組中元素的有序性,數(shù)組只被當(dāng)作一個(gè)存儲(chǔ)數(shù)據(jù)的集合的時(shí)候,為了避免大規(guī)模的數(shù)據(jù)搬移,我們可以對(duì)插入和刪除操作做一些優(yōu)化。例如:
如果要將某個(gè)數(shù)據(jù)插入到第 k 個(gè)位置,可以直接將第 k 為的數(shù)據(jù)搬移到數(shù)組元素的末尾,然后將新的元素值直接賦值給第 k 個(gè)元素;
如果要將第 k 個(gè)元素刪除,可以直接將數(shù)組的最后一個(gè)元素賦值給第 k 個(gè)元素,然后刪除最后一個(gè)元素即可。
這樣,其時(shí)間復(fù)雜度就會(huì)降為 O(1) 。
4. 容器與數(shù)組的比較對(duì)于數(shù)組類型,Java 中的 ArrayList 容器是基于數(shù)組實(shí)現(xiàn)的,那么二者相比各有什么優(yōu)點(diǎn)和適用場(chǎng)景呢?
ArrayList 的優(yōu)勢(shì)是方便,適合在一般的業(yè)務(wù)中使用。它將很多數(shù)組的操作細(xì)節(jié)封裝起來了,如數(shù)據(jù)的插入、刪除、數(shù)組的擴(kuò)容。ArrayList 無法存儲(chǔ)基本類型,比如 int、double,需要封裝為 Integer、Double 類,而自動(dòng)裝箱/拆箱的操作會(huì)有一定的性能消耗;
相對(duì)于容器來說,數(shù)組的使用雖然麻煩一點(diǎn),但它的性能會(huì)優(yōu)于容器,更適合用于底層的開發(fā)和追求極致性能的優(yōu)化。
二、數(shù)組擴(kuò)容及拷貝 1. 數(shù)組的擴(kuò)容數(shù)組是根據(jù)固定容量創(chuàng)建的,在必要的時(shí)候我們需要對(duì)數(shù)組 arr 進(jìn)行擴(kuò)容:
// 初始長度為 10 int[] arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i+1; } ... // 下面決定需要對(duì)數(shù)組 arr 進(jìn)行擴(kuò)容 int[] newArr = new int[arr.length*2]; // 對(duì)原數(shù)組進(jìn)行內(nèi)容拷貝 for (int i = 0; i < arr.length; i++) { newArr[i] = arr[i]; } arr = newArr;
在對(duì)數(shù)組進(jìn)行拷貝時(shí)除了利用 for 循環(huán)遍歷數(shù)組元素進(jìn)行拷貝外,推薦使用更高效的 System.arraycopy() 方法。
2. System.arraycopy() 方法拷貝數(shù)組System.arraycopy() 使用 native 關(guān)鍵字修飾,大大加快程序性能,為 JVM 內(nèi)部固有方法。它通過手工編寫匯編或其他優(yōu)化方法來進(jìn)行 Java 數(shù)組拷貝,這種方式比起直接在 Java 上進(jìn)行 for 循環(huán)或 clone 是更加高效的。數(shù)組越大體現(xiàn)地越明顯。
該方法用于從指定源數(shù)組中進(jìn)行拷貝操作,可以指定開始位置,拷貝指定長度的元素到指定目標(biāo)數(shù)組中。其聲明如下:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
參數(shù)說明:
src:要被復(fù)制的數(shù)組,
srcPos:被復(fù)制的數(shù)組開始復(fù)制的下標(biāo),
dest:目標(biāo)數(shù)組,也就是要把數(shù)據(jù)放進(jìn)來的數(shù)組,
destPos:從目標(biāo)數(shù)組第幾個(gè)下標(biāo)開始放入數(shù)據(jù),
length:被復(fù)制的數(shù)組中拿幾個(gè)數(shù)值放到目標(biāo)數(shù)組中;
例,數(shù)組 arr 進(jìn)行擴(kuò)容:
// 初始長度為 10 int[] arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i+1; } ... // 下面決定需要對(duì)數(shù)組 arr 進(jìn)行擴(kuò)容 int[] newArr = new int[arr.length*2]; System.arraycopy(arr,0,newArr,0,10); // 對(duì)原數(shù)組進(jìn)行內(nèi)容拷貝 arr = newArr;
絕大部分?jǐn)?shù)組和基于數(shù)組實(shí)現(xiàn)的容器(ArrayList 等)的擴(kuò)容都是基于 System.arraycopy() 方法進(jìn)行操作的。
歡迎您的點(diǎn)贊、收藏和評(píng)論!
(完)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/77472.html
摘要:本章節(jié)在此基礎(chǔ)上,對(duì)語言階段指針進(jìn)行更深層次的研究。數(shù)組指針的類型由數(shù)組類型決定,先找出數(shù)組的類型去掉名就是類型。相當(dāng)于數(shù)組指針?biāo)赶驍?shù)組的數(shù)組名。數(shù)組指針指向整個(gè)數(shù)組,將其看作二維數(shù)組并解引用得到一行的首元素,從而遍歷訪問。 ...
摘要:數(shù)組有以下特點(diǎn)無類型數(shù)組元素可以是任意元素。因此,當(dāng)小于數(shù)組最大索引時(shí),大于的數(shù)組元素會(huì)被刪除。原數(shù)組不會(huì)改變將數(shù)組元素轉(zhuǎn)換為字符串并連接在一起。默認(rèn)將數(shù)組元素用,連接,傳入的參數(shù)即為連接符。 showImg(https://box.worktile.com/view/fcfcdf2c99b14edfb6768085955ae253?pid=4b0845b09ca94218a955f8...
摘要:為了維持此規(guī)則不變化,數(shù)組有兩個(gè)特殊的行為。運(yùn)算符對(duì)數(shù)組返回并且對(duì)于除了函數(shù)以外的所有對(duì)象都是如此。解決方案是檢查對(duì)象的類屬性,對(duì)數(shù)組而言該屬 數(shù)組 數(shù)組是值的有序集合。每個(gè)值叫做一個(gè)元素,而每個(gè)元素在數(shù)組中有一個(gè)位置,以數(shù)字表示,稱為索引。 JavaScript 數(shù)組是無類型的,數(shù)組元素可以是任意類型,并且同一個(gè)數(shù)組中的不同元素也可能有不同的類型。數(shù)組的元素甚至也可能是對(duì)象或其他數(shù)組...
摘要:與稀疏數(shù)組對(duì)立的為密集數(shù)組,密集數(shù)組的索引會(huì)被持續(xù)的創(chuàng)建,并且其元素的數(shù)量等于其長度。創(chuàng)建一個(gè)長度為的數(shù)組,并初始化了個(gè)元素使用構(gòu)造函數(shù)創(chuàng)建數(shù)組對(duì)象的時(shí)候,關(guān)鍵字是可以省略的。另外使用和刪除元素是影響數(shù)組的長度的。 說明:本文只總結(jié)了JavaScript數(shù)組在web端的行為,不包括NodeJs端的行為。本文不涉及類型化數(shù)組(TypedArray)的討論、總結(jié)。 一、什么是數(shù)組 數(shù)組的定...
摘要:知識(shí)體系梳理流程圖一維數(shù)組數(shù)組概述數(shù)組是指一組數(shù)據(jù)的集合,數(shù)組中的每個(gè)數(shù)據(jù)被稱作元素。定義打印數(shù)組元素方法按照給定的格式打印題目分析通過觀察發(fā)現(xiàn),要實(shí)現(xiàn)按照指定格式,打印數(shù)組元素操作。按照這種方式,數(shù)組循環(huán)多圈以后,就完成了數(shù)組元素的排序。 知識(shí)體系梳理流程圖 showImg(https://segmentfault.com/img/bVXwAi?w=902&h=652); 一維數(shù)組 ...
摘要:數(shù)組是數(shù)據(jù)的有序列表,與其他語言不同的是,數(shù)組的每一項(xiàng)可以保存任何類型的數(shù)據(jù)。如下的代碼創(chuàng)建的就是一個(gè)密集數(shù)組稀疏數(shù)組與密集數(shù)組相反,并不強(qiáng)制要求數(shù)組元素是緊密相連的,即允許間隙的存在。 數(shù)組是數(shù)據(jù)的有序列表,與其他語言不同的是,ECMAScript 數(shù)組的每一項(xiàng)可以保存任何類型的數(shù)據(jù)。也就是說,可以用數(shù)組的第一個(gè)位置來保存字符串,用第二位置來保存數(shù)值,用第三個(gè)位置來保存對(duì)象, 以此類...
閱讀 3530·2023-04-25 18:52
閱讀 2551·2021-11-22 15:31
閱讀 1300·2021-10-22 09:54
閱讀 3077·2021-09-29 09:42
閱讀 661·2021-09-26 09:55
閱讀 991·2021-09-13 10:28
閱讀 1180·2019-08-30 15:56
閱讀 2166·2019-08-30 15:55