摘要:以下指代數(shù)組,指代數(shù)組列表。常見(jiàn)的轉(zhuǎn)換方法是或。在的使用過(guò)程中需要注意,當(dāng)要轉(zhuǎn)換的長(zhǎng)度小于的時(shí),不要試圖通過(guò)傳入形參的方式進(jìn)行轉(zhuǎn)換,雖然這在的長(zhǎng)度大于時(shí)不會(huì)出現(xiàn)問(wèn)題。所以,極度建議在轉(zhuǎn)換之前初始化的長(zhǎng)度為的,并且使用返回值重新給賦值。
Array 和 List 都是我們?cè)陂_(kāi)發(fā)過(guò)程中常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)。我們都知道 Array 是定長(zhǎng)的,List 是可變長(zhǎng)。而且,List 的實(shí)現(xiàn)類 ArrayList 也是根據(jù) Array 去實(shí)現(xiàn)的。
以下 Array 指代數(shù)組,List 指代數(shù)組列表。Array 轉(zhuǎn) List
當(dāng)然最原始的方法就是使用遍歷的方式,將 Array 中的元素都添加到 List 中。這種實(shí)現(xiàn)方式這里不作贅述。
Java1.2 之后,Jdk 語(yǔ)言提供 Arrays 這個(gè)工具類。大大簡(jiǎn)化了我們常見(jiàn)的 Array 操作,但是也有不少需要注意的問(wèn)題。
如下:
Integer[] a = { 1, 2 }; Listl = Arrays.asList(a);
這是我們常見(jiàn)的 Array 轉(zhuǎn)換 List 的方式,但是這個(gè)使用上有一個(gè)問(wèn)題。當(dāng)對(duì) List 對(duì)象 l 進(jìn)行列表插入操作時(shí):
l.add(3);
程序就會(huì)拋出異常 java.lang.UnsupportedOperationException。這是為什么呢?
查看 Arrays.asList 源碼發(fā)現(xiàn),
public staticList asList(T... a) { return new ArrayList<>(a); }
這里返回的 ArrayList 并不是 java.util.ArrayList 而是 java.util.Arrays.ArrayList。Arrays 又新建了一個(gè) ArrayList 內(nèi)部類,實(shí)現(xiàn)了一些基本 get set 方法。
回頭查看 java.util.Arrays.ArrayList.ArrayList(E[] array) 構(gòu)造函數(shù),
ArrayList(E[] array) { a = Objects.requireNonNull(array); }
不難發(fā)現(xiàn),java.util.Arrays.ArrayList 雖然打著 List 的旗號(hào),繼承了 AbstractList 。但是其只是在 Array 的基礎(chǔ)上進(jìn)行了簡(jiǎn)單的封轉(zhuǎn),AbstractList 中則是直接重寫(xiě)了 add 方法,表示這個(gè)方法是不允許操作。
public void add(int index, E element) { throw new UnsupportedOperationException(); }
明白了這個(gè)錯(cuò)誤產(chǎn)生的原因,回頭想一下 Java 的這些開(kāi)發(fā)者們?yōu)槭裁催@樣設(shè)計(jì)。
ArrayList 中如果要添加一個(gè)元素,則需要先對(duì)其內(nèi)部的 Array 進(jìn)行擴(kuò)容,然后將 Old Array 復(fù)制到擴(kuò)容后的 New Array 中。如果 Array 轉(zhuǎn) List 僅僅是讀取操作,或是在 Array 的 Size 范圍之內(nèi)進(jìn)行替換操作,再將 Array 復(fù)制一遍,不免會(huì)對(duì)內(nèi)存進(jìn)行浪費(fèi),倒不如直接將原始的 Array 直接拿來(lái)維護(hù)更為直接和高效(正如java.util.Arrays.ArrayList的實(shí)現(xiàn)方式)。
明白這個(gè)緣由之后,如果要在 Array 轉(zhuǎn) List 之后,不只有只讀操作,那么則需要下面的實(shí)現(xiàn),
Listl = new ArrayList<>(Arrays.asList(a));
雖然在我們?nèi)粘5拈_(kāi)發(fā)過(guò)程中,已經(jīng)習(xí)慣了使用 ArrayList 去代替 Array,但是了解此處 Java 的轉(zhuǎn)換過(guò)程還是能夠讓我們少踩坑。
List 轉(zhuǎn) Array因?yàn)?Array 的長(zhǎng)度不可變,所以這個(gè)轉(zhuǎn)換過(guò)程中,會(huì)有長(zhǎng)度不匹配的情況。
常見(jiàn)的轉(zhuǎn)換方法是 ArrayList.toArray() 或 ArrayList.toArray(T[])。
這兩個(gè)實(shí)現(xiàn)的共同點(diǎn)是都是對(duì) ArrayList 中的 Array 進(jìn)行 Copy 操作,生成一個(gè)新的數(shù)組返回。不同點(diǎn)是前者返回值是 Object[],后者是 T[]。
在 ArrayList.toArray(T[]) 的使用過(guò)程中需要注意,當(dāng)要轉(zhuǎn)換的 Array 長(zhǎng)度小于 ArrayList 的 size 時(shí),不要試圖通過(guò)傳入形參的方式進(jìn)行轉(zhuǎn)換,雖然這在 Array 的長(zhǎng)度大于 List 時(shí)不會(huì)出現(xiàn)問(wèn)題。
如下代碼:
// l [1, 2, 3] Integer[] a = new Integer[2]; l.toArray(a); // error 正確寫(xiě)法:a = l.toArray(a); Stream.of(a).forEach(System.out::println);
輸出結(jié)果是:null null。
查看源碼實(shí)現(xiàn):
publicT[] toArray(T[] a) { if (a.length < size) // Make a new array of a"s runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } // Arrays.copyOf public static T[] copyOf(U[] original, int newLength, Class extends T[]> newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
可見(jiàn),當(dāng) a.length < size 成立,入?yún)?a 并沒(méi)有被使用,所以 a 依然是 new Integer[2]。
所以,極度建議在轉(zhuǎn)換之前初始化 Array 的長(zhǎng)度為 ArrayList 的 size,并且使用返回值重新給 Array 賦值。
// l [1, 2, 3] Integer[] b = new Integer[l.size()]; l.toArray(b); Stream.of(b).forEach(System.out::println);
原文地址:https://xdbin.com/blog/8a9eec5167da2d4501681e8c3f180001
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73103.html
摘要:通過(guò)對(duì)一系列任務(wù)建模來(lái)理解一些非常重要的函數(shù)式編程在列表操作中的價(jià)值一些些看起來(lái)不像列表的語(yǔ)句作為列表操作,而不是單獨(dú)執(zhí)行。映射我們將采用最基礎(chǔ)和最簡(jiǎn)單的操作來(lái)開(kāi)啟函數(shù)式編程列表操作的探索。函子是采用運(yùn)算函數(shù)有效用操作的值。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個(gè)流淌著...
摘要:堆棧和隊(duì)列稱為線性數(shù)據(jù)結(jié)構(gòu),而圖形和樹(shù)是非線性數(shù)據(jù)結(jié)構(gòu)。在單次運(yùn)行期間,可能無(wú)法遍歷非線性數(shù)據(jù)結(jié)構(gòu)中的所有數(shù)據(jù)項(xiàng)。堆棧是根據(jù)概念插入和移除的對(duì)象的容器。將元素添加到堆棧時(shí),它被稱為推送操作,而當(dāng)您刪除或刪除元素時(shí),它被稱為彈出操作。 概述 ????數(shù)據(jù)結(jié)構(gòu)是組織數(shù)據(jù)的方式,以便能夠更好的存儲(chǔ)和獲取數(shù)據(jù)。數(shù)據(jù)結(jié)構(gòu)定義數(shù)據(jù)之間的關(guān)系和對(duì)這些數(shù)據(jù)的操作方式。數(shù)據(jù)結(jié)構(gòu)屏蔽了數(shù)據(jù)存儲(chǔ)和操作的細(xì)節(jié)...
摘要:提供了排序,查找等功能。常用操作常用的操作之一用于基本數(shù)據(jù)類型與字符串之間的轉(zhuǎn)換。 1_StringBuffer類的概述 A:StringBuffer類概述 通過(guò)JDK提供的API,查看StringBuffer類的說(shuō)明 線程安全的可變字符序列 (一個(gè)類似于 String 的字符串緩沖區(qū),但不能修改 : 不能像String那樣用 + 連接來(lái)修改String) B:String...
摘要:方法詳解我在一開(kāi)始看到的函數(shù)和時(shí)非常的模糊看也看不懂最近在網(wǎng)上看到一些文章對(duì)方法和的一些示例總算是看的有點(diǎn)眉目了在這里我做如下筆記希望和大家分享如有什么不對(duì)的或者說(shuō)法不明確的地方希望讀者多多提一些意見(jiàn)以便共同提高主要我是要解決一下幾個(gè)問(wèn)題和 Js apply方法詳解我在一開(kāi)始看到j(luò)avascript的函數(shù)apply和call時(shí),非常的模糊,看也看不懂,最近在網(wǎng)上看到一些文章對(duì)apply...
摘要:不相等的對(duì)象要具有不相等的哈希碼為了哈希表的操作效率,這一點(diǎn)很重要,但不是強(qiáng)制要求,最低要求是不相等的對(duì)象不能共用一個(gè)哈希碼。方法和方法協(xié)同工作,返回對(duì)象的哈希碼。這個(gè)哈希碼基于對(duì)象的身份生成,而不是對(duì)象的相等性。 本文面向 剛學(xué)完Java的新手們。這篇文章不講語(yǔ)法,而是一些除了語(yǔ)法必須了解的概念。 將要去面試的初級(jí)工程師們。查漏補(bǔ)缺,以免遭遇不測(cè)。 目前由于篇幅而被挪出本文的知識(shí)...
閱讀 2173·2021-09-04 16:40
閱讀 1471·2021-08-13 15:07
閱讀 3612·2019-08-30 15:53
閱讀 3203·2019-08-30 13:11
閱讀 1082·2019-08-29 17:22
閱讀 1821·2019-08-29 12:47
閱讀 1481·2019-08-29 11:27
閱讀 2235·2019-08-26 18:42