日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Array 和 List 的转换问题

發布時間:2024/5/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Array 和 List 的转换问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Array 和 List 都是我們在開發過程中常見的數據結構。我們都知道 Array 是定長的,List 是可變長。而且,List 的實現類 ArrayList 也是根據 Array 去實現的。

以下 Array 指代數組,List 指代數組列表。

Array 轉 List

當然最原始的方法就是使用遍歷的方式,將 Array 中的元素都添加到 List 中。這種實現方式這里不作贅述。

Java1.2 之后,Jdk 語言提供 Arrays 這個工具類。大大簡化了我們常見的 Array 操作,但是也有不少需要注意的問題。

如下:

Integer[] a = { 1, 2 }; List<Integer> l = Arrays.asList(a);

這是我們常見的 Array 轉換 List 的方式,但是這個使用上有一個問題。當對 List 對象 l 進行列表插入操作時:

l.add(3);

程序就會拋出異常 java.lang.UnsupportedOperationException。這是為什么呢?

查看 Arrays.asList 源碼發現,

public static <T> List<T> asList(T... a) {return new ArrayList<>(a); }

這里返回的 ArrayList 并不是 java.util.ArrayList 而是 java.util.Arrays.ArrayList。Arrays 又新建了一個 ArrayList 內部類,實現了一些基本 get set 方法。

回頭查看 java.util.Arrays.ArrayList.ArrayList(E[] array) 構造函數,

ArrayList(E[] array) {a = Objects.requireNonNull(array); }

不難發現,java.util.Arrays.ArrayList 雖然打著 List 的旗號,繼承了 AbstractList 。但是其只是在 Array 的基礎上進行了簡單的封轉,AbstractList 中則是直接重寫了 add 方法,表示這個方法是不允許操作。

public void add(int index, E element) {throw new UnsupportedOperationException(); }

明白了這個錯誤產生的原因,回頭想一下 Java 的這些開發者們為什么這樣設計。

ArrayList 中如果要添加一個元素,則需要先對其內部的 Array 進行擴容,然后將 Old Array 復制到擴容后的 New Array 中。如果 Array 轉 List 僅僅是讀取操作,或是在 Array 的 Size 范圍之內進行替換操作,再將 Array 復制一遍,不免會對內存進行浪費,倒不如直接將原始的 Array 直接拿來維護更為直接和高效(正如java.util.Arrays.ArrayList的實現方式)。

明白這個緣由之后,如果要在 Array 轉 List 之后,不只有只讀操作,那么則需要下面的實現,

List<Integer> l = new ArrayList<>(Arrays.asList(a));

雖然在我們日常的開發過程中,已經習慣了使用 ArrayList 去代替 Array,但是了解此處 Java 的轉換過程還是能夠讓我們少踩坑。

List 轉 Array

因為 Array 的長度不可變,所以這個轉換過程中,會有長度不匹配的情況。

常見的轉換方法是 ArrayList.toArray() 或 ArrayList.toArray(T[])。

這兩個實現的共同點是都是對 ArrayList 中的 Array 進行 Copy 操作,生成一個新的數組返回。不同點是前者返回值是 Object[],后者是 T[]。

在 ArrayList.toArray(T[]) 的使用過程中需要注意,當要轉換的 Array 長度小于 ArrayList 的 size 時,不要試圖通過傳入形參的方式進行轉換,雖然這在 Array 的長度大于 List 時不會出現問題。

如下代碼:

// l [1, 2, 3] Integer[] a = new Integer[2]; l.toArray(a); // error 正確寫法:a = l.toArray(a); Stream.of(a).forEach(System.out::println);

輸出結果是:null null。

查看源碼實現:

public <T> T[] 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,U> 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; }

可見,當 a.length < size 成立,入參 a 并沒有被使用,所以 a 依然是 new Integer[2]。

所以,極度建議在轉換之前初始化 Array 的長度為 ArrayList 的 size,并且使用返回值重新給 Array 賦值。

// l [1, 2, 3] Integer[] b = new Integer[l.size()]; b = l.toArray(b); Stream.of(b).forEach(System.out::println);

備注

部分內容參考:《碼出高效:Java開發手冊》 一書。

原文地址

總結

以上是生活随笔為你收集整理的Array 和 List 的转换问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。