欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

由淺到深帶你詳談Java實現(xiàn)數(shù)組擴容的三種方式

 更新時間:2023年06月05日 11:12:33   作者:程序yang  
這篇文章主要詳細介紹了Java實現(xiàn)數(shù)組擴容的三種方式,新建一個數(shù)組,把原來數(shù)組的內(nèi)容搬到新數(shù)組中,使用system.arraycopy(),使用java.util.Arrays.copyOf()這三種方式,具有一定的參考價值,需要的朋友可以借鑒一下

1.新建一個數(shù)組,把原來數(shù)組的內(nèi)容搬到新數(shù)組中。

這種方法實現(xiàn)的思路是:先新建一個數(shù)組(前提條件是長度得比原來的長),然后把原來數(shù)組的內(nèi)容搬到新數(shù)組中.

案例分析:

public static void main(String[] args) {
	// 利用函數(shù)的方法進行數(shù)組的擴充
	// 定義一個小型的數(shù)組
	int[] a = { 1, 2, 3, 4, 5 };
	// 調(diào)用擴容函數(shù)
	a= expand1(a);
	// 測試是否擴容完成,輸出此時數(shù)組a中的值
	for (int i = 0; i < a.length; i++) {
		System.out.println("數(shù)組元素:" + a[i]);
	}
}
// 擴容函數(shù)1,
public static int[] expand1(int a[]) {
	// 定義一個新數(shù)組b,并為其賦值長度為數(shù)組a的二倍
	int b[] = new int[a.length * 2];
	// 將數(shù)組a的元素循環(huán)遍歷到數(shù)組b中
	for (int i = 0; i < a.length; i++) {
		b[i] = a[i];
	}
	System.out.println("數(shù)組擴容方法1:" + Arrays.toString(b));
	return b;
}

輸出結(jié)果:

數(shù)組擴容方法1:[1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
數(shù)組元素:1
數(shù)組元素:2
數(shù)組元素:3
數(shù)組元素:4
數(shù)組元素:5
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0

2.使用system.arraycopy()

常用作數(shù)組的擴容,如ArrayList底層數(shù)組的擴容

方法解析:

public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

通過上面的源碼可以看到,arraycopy它是一個靜態(tài)本地方法,由虛擬機實現(xiàn),效率自然比用java一個個復制高。

將指定源數(shù)組中的數(shù)組從指定位置開始復制到目標數(shù)組的指定位置。 陣列組件的一個子序列被從通過引用的源陣列復制src被引用的目標陣列dest 。 復制的組件數(shù)等于length參數(shù)。 在位置的部件srcPos通過srcPos+length-1源陣列中的被復制到的位置destPos通過destPos+length-1分別,目的地陣列。

大白話總結(jié):
從源數(shù)組src取元素,范圍為下標srcPos到srcPos+length-1,取出共length個元素,存放到目標數(shù)組中,存放位置為下標destPos到destPos+length-1。簡單說,就是數(shù)組間的復制。

參數(shù)解釋:

  • src 源數(shù)組;
  • srcPos 源數(shù)組中的起始位置;
  • dest 目標數(shù)組;
  • destPos 目標數(shù)組中的起始位置;
  • length 要復制的數(shù)組元素的數(shù)量

注意事項:

  •  1.若src和dest參數(shù)引用相同的數(shù)組對象,則執(zhí)行復制,就好像位置 srcPos 到 srcPos + length - 1 的組件首次復制到具有 length 組件的臨時數(shù)組,然后臨時數(shù)組的內(nèi)容被復制到位置 destPos 通過目標數(shù)組的 destPos + length - 1 。
  •  2.若 src 是 null ,則拋java.lang.NullPointerException異常,并且不修改目標陣列。案例演示如下:
public static void main(String[] args) {
	int[] src = { 1, 2, 3, 4 };
	int[] dest = null;
	System.arraycopy(src, 0, dest, 0, 4);//拋異常:java.lang.NullPointerException
	for (Object o : dest) {
		System.out.println(o);
	}
}

解析:
src源數(shù)組共有4個元素,索引是0-3,
dest目標數(shù)組為null,
當執(zhí)行System.arraycopy(src, 0, dest, 0, 4);時,
第一步:由于dest為null,arraycopy方法檢查到null操作,所以就會拋空指針異常。(如果你想深入理解,可以去了解一下arraycopy的底層源碼。)

  • 3.srcPos 的設置主要看 destPos 和 length ,若 srcPos 該位置往后的元素少于要復制的數(shù)組元素的數(shù)量(即 srcPos + length 的長度已經(jīng)超過源數(shù)組元素的數(shù)量/個數(shù),不是長度/索引;或者 destPos + length 的長度已經(jīng)超過目標數(shù)組元素的數(shù)量/個數(shù),不是長度/索引;),則會拋java.lang.ArrayIndexOutOfBoundsException異常。案例演示如下:
//src.length < srcPos + length
public static void main(String[] args) {
	String[] src = { "aa", "bb", "cc", "dd" };
	String[] dest = new String[] { "a", "b", "c", "d", "e" };
	System.arraycopy(src, 1, dest, 1, 4);//拋異常java.lang.ArrayIndexOutOfBoundsException
	for (Object o : dest) {
		System.out.println(o);
	}
}

解析:
src源數(shù)組共有4個元素,索引是0-3,
dest目標數(shù)組共有5個元素,索引是0-4,
當執(zhí)行System.arraycopy(src, 1, dest, 1, 4);時,
第一步:srcPos為1,即從源數(shù)組(src)中,從下標1開始取,
第二步:length為4,即取4個元素,也就是src[1]-src[4],即從“bb”之后要取4個元素,這時源數(shù)組(src)只有“bb”、“cc”、“dd” 3個元素,明顯不夠4個元素,所以就會拋數(shù)組索引越界異常。

//dest.length < destPos + length
public static void main(String[] args) {
	String[] src = { "aa", "bb", "cc", "dd" };
	String[] dest = new String[] { "a", "b", "c", "d", "e" };
	System.arraycopy(src, 0, dest, 2, 4);//拋異常java.lang.ArrayIndexOutOfBoundsException
	for (Object o : dest) {
		System.out.println(o);
	}
}

解析:
src源數(shù)組共有4個元素,索引是0-3,
dest目標數(shù)組共有5個元素,索引是0-4,
當執(zhí)行System.arraycopy(src, 0, dest, 2, 4);時,
第一步:srcPos為0,即從源數(shù)組(src)中,從下標0開始取,
第二步:length為4,即取4個元素,也就是src[0]-src[3],即從“aa”之后要取4個元素;分別是“aa”、“bb”、“cc”、“dd” 4個元素
第三步:把從源數(shù)組(src)取出的數(shù)(“aa”、“bb”、“cc”、“dd” 4個元素),按順序,存放到目標數(shù)組(dest)中,從下標2開始存,存4個,也就是dest[2]-dest[5],由于dest目標數(shù)組最大索引為4,只能存放“aa”、“bb”、“cc”,存不下“dd”,即不夠容量存放4個數(shù),所以就會拋數(shù)組索引越界異常。

  • 4.若 dest 是 null ,則拋java.lang.NullPointerException異常,同上/參考2。
  •  5.destPos 的設置主要看 srcPos 和 length ,若 destPos 該位置容納不下要復制的數(shù)組元素(即 destPos + length 的長度已經(jīng)超過目標數(shù)組元素的數(shù)量/個數(shù),不是長度/索引;或者 srcPos + length 的長度已經(jīng)超過源數(shù)組元素的數(shù)量/個數(shù),不是長度/索引;),則會拋java.lang.ArrayIndexOutOfBoundsException異常。同上/參考3。
  •  6.length 的設置主要看 srcPos 和 destPos,若 length 超出源數(shù)組中的起始位置之后的元素數(shù)量(即 srcPos 往后的元素數(shù)量/個數(shù),不是長度/索引 )或者 length 超出目標數(shù)組中的起始位置的元素數(shù)量(即 destPos 往后的元素數(shù)量/個數(shù),不是長度/索引),則會拋java.lang.ArrayIndexOutOfBoundsException異常。
// length > srcPos.length - srcPos[index]
public static void main(String[] args) {
	String[] src = { "aa", "bb", "cc", "dd" };
	String[] dest = new String[] { "a", "b", "c", "d", "e" };
	System.arraycopy(src, 2, dest, 2, 3);// 拋異常java.lang.ArrayIndexOutOfBoundsException
	for (Object o : dest) {
		System.out.println(o);
	}
}

解析:
src源數(shù)組共有4個元素,索引是0-3,
dest目標數(shù)組共有5個元素,索引是0-4,
當執(zhí)行System.arraycopy(src, 2, dest, 2, 3);時,
第一步:srcPos為2,即從源數(shù)組(src)中,從下標2開始取,
第二步:length為3,即取3個元素,也就是src[2]-src[4],即從“cc”之后要取3個元素,這時源數(shù)組(src)只有“cc”、“dd” 2個元素,明顯不夠3個元素,所以就會拋數(shù)組索引越界異常。

// length > destPos.length - destPos[index]
public static void main(String[] args) {
	String[] src = { "aa", "bb", "cc", "dd" };
	String[] dest = new String[] { "a", "b", "c", "d", "e" };
	System.arraycopy(src, 2, dest, 4, 2);// 拋異常java.lang.ArrayIndexOutOfBoundsException
	for (Object o : dest) {
		System.out.println(o);
	}
}

解析:
src源數(shù)組共有4個元素,索引是0-3,
dest目標數(shù)組共有5個元素,索引是0-4,
當執(zhí)行System.arraycopy(src, 2, dest, 4, 2);時,
第一步:srcPos為2,即從源數(shù)組(src)中,從下標2開始取,
第二步:length為2,即取2個元素,也就是src[2]-src[3],即從“cc”之后要取2個元素,分別是“cc”、“dd” 2個元素;
第三步:把從源數(shù)組(src)取出的數(shù)(“cc”、“dd” 2個元素),按順序,存放到目標數(shù)組(dest)中,從下標4開始存,存2個,也就是dest[4]-dest[5],由于dest目標數(shù)組最大索引為4,只能存放“cc”,存不下“dd”,即不夠容量存放2個數(shù),所以就會拋數(shù)組索引越界異常。

  • 7.當srcPos 、destPos 和 length 任意一個參數(shù)小于0時,則會拋java.lang.ArrayIndexOutOfBoundsException異常。
//srcPos < 0 || destPos < 0 || length < 0
public static void main(String[] args) {
	String[] src = { "aa", "bb", "cc", "dd" };
	String[] dest = new String[] { "a", "b", "c", "d", "e" };
	System.arraycopy(src, -1, dest, 1, 1);//拋異常java.lang.ArrayIndexOutOfBoundsException
	for (Object o : dest) {
		System.out.println(o);
	}
}

解析:
src源數(shù)組共有04個元素,索引是0-3,
dest目標數(shù)組共有5個元素,索引是0-4,
當執(zhí)行System.arraycopy(src, -1, dest, 1, 1);時,
第一步:srcPos為-1,不在索引0-3范圍內(nèi),所以就會拋數(shù)組索引越界異常。

??補充點:

  •  8.當源數(shù)組和目標數(shù)組兩組數(shù)據(jù)的元素類型不匹配時,則會拋java.lang.ArrayStoreException異常,并且不修改目標數(shù)組。
public static void main(String[] args) {
	int[] src = { 1, 2, 3, 4 };
	Object[] dest = new Object[3];
	System.arraycopy(src, 0, dest, 0, 3);//拋異常java.lang.ArrayStoreException
	for (Object o : dest) {
		System.out.println(o);
	}
}

public static void main(String[] args) {
	Object[] src = { 1, 2, 3, 4 };
	int[] dest = new int[3];
	System.arraycopy(src, 0, dest, 0, 3);// 拋異常java.lang.ArrayStoreException
	for (Object o : dest) {
		System.out.println(o);
	}
}

若源數(shù)組src的元素為目標數(shù)組dest的元素的子類時,是可以復制的,特殊地,如int不是Object的子類(或者說,不存在繼承的概念),所以,上述代碼中,如果把int[] src = {1, 2, 3, 4};改為Integer[] src = {1, 2, 3, 4};,是不會報錯的。

public static void main(String[] args) {
	Integer[] src = { 1, 2, 3, 4 };
	Object[] dest = new Object[3];
	System.arraycopy(src, 0, dest, 0, 3);
	for (Object o : dest) {
		System.out.println(o);
	}
}

輸出結(jié)果:

1
2
3

public static void main(String[] args) {
	Object[] src = { 1, 2, 3, 4 };
	Integer[] dest = new Integer[3];
	System.arraycopy(src, 0, dest, 0, 3);
	for (Object o : dest) {
		System.out.println(o);
	}
}

輸出結(jié)果:

1
2
3

總結(jié):

java.lang.ArrayStoreException異常(由于類型不匹配, src陣列中的元素無法存儲到 dest陣列中),常見的就是:

  • src參數(shù)引用的對象不是數(shù)組。
  • dest參數(shù)引用的對象不是數(shù)組。
  • src參數(shù)和dest參數(shù)引用其組件類型為不同基元類型的數(shù)組。
  • src參數(shù)引用具有基本組件類型的數(shù)組,而dest參數(shù)引用具有引用組件類型的數(shù)組。
  • src參數(shù)引用具有引用組件類型的數(shù)組,而dest參數(shù)引用具有基本組件類型的數(shù)組。

java.lang.ArrayIndexOutOfBoundsException異常(如果復制會導致訪問數(shù)組邊界外的數(shù)據(jù)),常見的就是:

  • srcPos論點是否定的。
  • destPos參數(shù)為負數(shù)。
  • length參數(shù)為負數(shù)。
  • srcPos+length大于src.length ,源數(shù)組的長度。
  • destPos+length大于dest.length ,目標數(shù)組的長度。

java.lang.NullPointerException異常,常見的就是:

  • src或 dest 是 null 。

案例分析:

public static void main(String[] args) {
	// 利用函數(shù)的方法進行數(shù)組的擴充
	// 定義一個小型的數(shù)組
	int[] a = { 1, 2, 3, 4, 5 };
	// 調(diào)用擴容函數(shù)
	a= expand2(a);
	// 測試是否擴容完成,輸出此時數(shù)組a中的值
	for (int i = 0; i < a.length; i++) {
		System.out.println("數(shù)組元素:" + a[i]);
	}
}
// 數(shù)組擴容方法2,利用系統(tǒng)函數(shù)arraycopy進行擴容
public static int[] expand2(int a[]) {
	int[] b = new int[a.length * 2];
	// 系統(tǒng)函數(shù)進行擴容,將a[]的值賦值到b[]中,共a.length個長度。
	System.arraycopy(a, 0, b, 0, a.length);
	System.out.println("數(shù)組擴容方法2:" + Arrays.toString(b));
	return b;
}

輸出結(jié)果:

數(shù)組擴容方法2:[1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
數(shù)組元素:1
數(shù)組元素:2
數(shù)組元素:3
數(shù)組元素:4
數(shù)組元素:5
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0

3.使用java.util.Arrays.copyOf()

方法解析:

Arrays.copyof是用于數(shù)組進行復制時常使用的方法,本身在Arrays類里面,而之所以能這么使用而不用創(chuàng)建對象在于該方法本身由static修飾,被static修飾的方法可以在該類創(chuàng)建對象前載入jvm。

Arrays.copyof有眾多的重載方法,以最典型的Arrays.copyOf(srcArray, length);為例進行分析,源碼如下:

public static long[] copyOf(long[] original, int newLength) {
    long[] copy = new long[newLength];
    System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
    return copy;
}

通過上面的代碼可以看出,其本質(zhì)是調(diào)用了System.arraycopy方法。

  • 1.先產(chǎn)生一個新的數(shù)組
  • 2.調(diào)用arraycopy方法
  • 3.返回產(chǎn)生的新數(shù)組

參數(shù)解釋:

  • original 源數(shù)組
  • newLength 新擴容長度

注意事項:

當我們將原來的數(shù)組進行擴容的時候,調(diào)用該方法產(chǎn)生了一個新的數(shù)組,而將擴容后的數(shù)組賦值給原來的數(shù)組的時候,原數(shù)組指向新產(chǎn)生的數(shù)組,但其原數(shù)組的內(nèi)容依然在內(nèi)存中,等待jvm回收,在這段時間中其實是造成了內(nèi)存的浪費,所以使用該方法盡管簡便,實際上有一定的不足。

案例分析:

public static void main(String[] args) {
	// 利用函數(shù)的方法進行數(shù)組的擴充
	// 定義一個小型的數(shù)組
	int[] a = { 1, 2, 3, 4, 5 };
	// 調(diào)用擴容函數(shù)
	a= expand3(a);
	// 測試是否擴容完成,輸出此時數(shù)組a中的值
	for (int i = 0; i < a.length; i++) {
		System.out.println("數(shù)組元素:" + a[i]);
	}
}
// 數(shù)組擴容方法3,利用系統(tǒng)函數(shù)copyOf進行擴容
public static int[] expand3(int a[]) {
	int[] b = java.util.Arrays.copyOf(a, a.length * 2);
	System.out.println("數(shù)組擴容方法3:" + Arrays.toString(b));
	return b;
}

輸出結(jié)果:

數(shù)組擴容方法3:[1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
數(shù)組元素:1
數(shù)組元素:2
數(shù)組元素:3
數(shù)組元素:4
數(shù)組元素:5
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0
數(shù)組元素:0

Java數(shù)組擴容的原理:
  •  Java數(shù)組對象的大小是固定不變的,數(shù)組對象是不可擴容的。
  •  利用數(shù)組復制方法可以變通的實現(xiàn)數(shù)組擴容。
  • System.arraycopy()可以復制數(shù)組。
  •  Arrays.copyOf()可以簡便的創(chuàng)建數(shù)組副本。
  •  創(chuàng)建數(shù)組副本的同時將數(shù)組長度增加就變相的實現(xiàn)了數(shù)組的擴容。

總結(jié):

只有數(shù)組為一維數(shù)組,并且元素為基本類型或String類型時,才是深拷貝,其它都屬于淺拷貝。

拷貝的兩層含義,對應了淺拷貝和深拷貝的概念,做了第一層,就是淺拷貝,做到第二層,就是深拷貝。

  • 淺拷貝:將原對象或原數(shù)組的引用直接賦給新對象,新數(shù)組,新對象/數(shù)組只是原對象的一個引用。
  • 深拷貝:創(chuàng)建一個新的對象和數(shù)組,將原對象的各項屬性的“值”(數(shù)組的所有元素)拷貝過來,是“值”而不是“引用”。

很容易可以想到,淺拷貝比深拷貝要更快,但是,從拷貝的意義上來看,淺拷貝相較于深拷貝,要欠缺一點,即一個是效率問題,一個是內(nèi)存占用問題。

以上就是由淺到深帶你詳談Java實現(xiàn)數(shù)組擴容的三種方式的詳細內(nèi)容,更多關(guān)于Java實現(xiàn)數(shù)組擴容的三種方式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 超細致講解Spring框架 JdbcTemplate的使用

    超細致講解Spring框架 JdbcTemplate的使用

    在之前的Javaweb學習中,學習了手動封裝JdbcTemplate,其好處是通過(sql語句+參數(shù))模板化了編程。而真正的JdbcTemplate類,是Spring框架為我們寫好的。它是 Spring 框架中提供的一個對象,是對原始 Jdbc API 對象的簡單封裝。
    2021-09-09
  • lombok插件無法使用的原因及解決方案

    lombok插件無法使用的原因及解決方案

    這篇文章主要介紹了lombok插件無法使用的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 詳解Java串行化接口的用法和原理

    詳解Java串行化接口的用法和原理

    在Java開發(fā)中,我們經(jīng)常需要將對象進行序列化和反序列化,以便在網(wǎng)絡傳輸或存儲到持久化介質(zhì)中,Java提供了一種機制,即通過實現(xiàn)Serializable接口來實現(xiàn)對象的串行化,本文將詳細介紹Java串行化接口的用法和原理,以及一些相關(guān)的注意事項,需要的朋友可以參考下
    2023-11-11
  • Java設計模式之java模板方法模式詳解

    Java設計模式之java模板方法模式詳解

    這篇文章主要介紹了Java設計模式模板方法模式(Template)用法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2021-09-09
  • java agent使用全解析

    java agent使用全解析

    這篇文章主要介紹了javaagent的相關(guān)資料,文中示例代碼非常詳細,供大家參考和學習,感興趣的朋友可以了解下
    2020-07-07
  • 詳解Java接口簽名(Signature)實現(xiàn)方案

    詳解Java接口簽名(Signature)實現(xiàn)方案

    這篇文章主要介紹了Java接口簽名(Signature)實現(xiàn)方案?,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • 解決MyBatisPlus的updateBatchById()批量修改失效問題

    解決MyBatisPlus的updateBatchById()批量修改失效問題

    這篇文章主要介紹了解決MyBatisPlus的updateBatchById()批量修改失效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java中l(wèi)ambda表達式的基本運用

    Java中l(wèi)ambda表達式的基本運用

    大家好,本篇文章主要講的是Java中l(wèi)ambda表達式的基本運用,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • list的4種遍歷方式(實例講解)

    list的4種遍歷方式(實例講解)

    下面小編就為大家?guī)硪黄猯ist的4種遍歷方式(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Mybatis如何使用動態(tài)語句實現(xiàn)批量刪除(delete結(jié)合foreach)

    Mybatis如何使用動態(tài)語句實現(xiàn)批量刪除(delete結(jié)合foreach)

    這篇文章主要介紹了Mybatis如何使用動態(tài)語句實現(xiàn)批量刪除(delete結(jié)合foreach),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論