陣列轉集合、集合轉陣列、字串陣列與int型、long型陣列等的轉換
在專案中經常會遇到陣列轉集合、集合轉陣列、陣列之間型別轉換等操作
1.陣列轉集合
為了實現把一個數組轉換成一個ArrayList,很多Java程式設計師會使用如下的程式碼:
String str[] = {"1","2","3"};
List<String> strings = Arrays.asList(str);
Arrays.asList確實會返回一個ArrayList物件,但是該類是Arrays類 中一個私有靜態內部類,而不是常見的java.util.ArrayList類。這個java.util.Arrays.ArrayList類具有 set(),get(),contains()等方法,但是不具有任何新增或移除元素的任何方法。因為該類的大小(size)是固定的。如果新增元素是會報錯的
String str[] = {"1","2","3"}; List<String> strings = Arrays.asList(str); strings.add("eee");
報錯如下:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at Test.test1(Test.java:31)
at Test.main(Test.java:24)
為了創建出一個真正的ArrayList,程式碼應該如下所示:(這種方法建立的集合可以進行集合的增加)
String str[] = {"1","2","3"}; List<String> strings = new ArrayList<String>(Arrays.asList(str)); strings.add("4"); System.out.println(strings);
更加高效的程式碼如下:
String str[] = {"1","2","3"}; List<String> strings = new ArrayList<String>(str.length); Collections.addAll(strings,str); strings.add("4"); System.out.println(strings);
2.集合轉陣列
(1)錯誤演示
很多人習慣下面用法:
List<String> strings = new ArrayList<String>(); String[] objects = (String[]) strings.toArray();
編譯通過,執行報錯如下:
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at Test.test1(Test.java:32)
at Test.main(Test.java:26)
學過JVM的應該知道上面的意思是Object陣列不能轉變為String陣列。[代表以為陣列,L代表陣列的元素是引用型別,後面是具體的元素型別
對於這個現象我們可以這麼解釋:Java中允許向上和向下轉型,但是這個轉型是否成功是根據Java虛擬機器中這個物件的型別來實現的。Java虛擬機器中儲存 了每個物件的型別。而陣列也是一個物件。陣列的型別是[Ljava.lang.Object。把[Ljava.lang.Object轉換成 [Ljava.lang.String是顯然不可能的事情,因為這裡是一個向下轉型,而虛擬機器只儲存了這是一個Object的陣列,不能保證陣列中的元素 是String的,所以這個轉型不能成功。數組裡面的元素只是元素的引用,不是儲存的具體元素,所以陣列中元素的型別還是儲存在Java虛擬機器中的。
根據上面的解釋,我們可以把這個問題歸納到下面這個模型:
Object objs[]=new Object[10]; String strs[]=(String[])objs;
這樣子和剛才上面編譯錯誤是一樣的。如果我們修改一下這個程式碼,如下:
String strs[]=new String[10]; Object objs[]=strs;
這樣子就可以編譯通過了。所以這個問題我們可以歸結為一個Java轉型規則的問題。
(2)正確的做法:(延伸一點直接列印陣列列印的是陣列的)
最菜雞的做法是:
List<String> list = new ArrayList<String>(); list.add("1"); String strings[]=new String[list.size()]; for(int i=0,j=list.size();i<j;i++){ strings[i]=list.get(i); } System.out.println(strings); System.out.println(strings.getClass()); System.out.println(Arrays.toString(strings));
結果:
[Ljava.lang.String;@20724356
class [Ljava.lang.String;
[1]
比較簡便的做法:
List<String> list = new ArrayList<String>(); list.add("1"); String[] strings = new String[list.size()]; list.toArray(strings); System.out.println(strings); System.out.println(strings.getClass()); System.out.println(Arrays.toString(strings));
結果同上。
3.陣列轉陣列--程式碼用到了commons-beanutils包
最常見的就是字串陣列型別轉int、long陣列,或者字串型別轉Integer、Long、Integer型轉int(也就是包裝型別轉原始型別)。
最原始的for迴圈轉換賦值在這裡就不試了。
陣列型別的轉換:
import org.apache.commons.beanutils.ConvertUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class Test { public static void main(String[] args) { String str[] = { "1", "2", "3" }; // 字串陣列轉long陣列 long[] str2lon = (long[]) ConvertUtils.convert(str, long.class); System.out.println(str2lon); // 字串陣列轉Long陣列 Long[] str2Lon = (Long[]) ConvertUtils.convert(str, Long.class); System.out.println(str2Lon); // 字串陣列轉int陣列 int[] str2int = (int[]) ConvertUtils.convert(str, int.class); System.out.println(str2int); // 字串陣列轉Integer陣列 Integer[] str2Int = (Integer[]) ConvertUtils.convert(str, Integer.class); System.out.println(str2Int); // int型陣列轉為String陣列 String int2Str[] = (String[]) ConvertUtils.convert(str2int, String[].class); System.out.println(int2Str); // Integer型陣列轉為String陣列 String Int2Str[] = (String[]) ConvertUtils.convert(str2Int, String[].class); System.out.println(Int2Str); // long型陣列轉為String陣列 String lon2str[] = (String[]) ConvertUtils.convert(str2lon, String[].class); System.out.println(lon2str); String Lon2str[] = (String[]) ConvertUtils.convert(str2Lon, String[].class); System.out.println(Lon2str); } }
[Ljava.lang.Long;@7c23b1e1
[Ljava.lang.Integer;@4651a9e4
[Ljava.lang.String;@1b68dbcd
[Ljava.lang.String;@1367dca
[Ljava.lang.String;@207c5965
[Ljava.lang.String;@43d1068c
關於包裝型別轉原始類,可以用commons-lang包的ArrayUtils操作,參考:https://www.cnblogs.com/qlqwjy/p/9467178.html
補充:補充一點JVM相關知識
在Java中,任何型別都有class,包括基本資料型別與void。在Java中 [ 代表陣列, [[ 代表二維陣列。依次類推。
其他的描述識別符號如下:
B---基本資料型別byte
C---基本資料型別char
D---基本資料型別double
F---基本資料型別float
I---基本資料型別int
J---基本資料型別long
S---基本資料型別short
Z---基本資料型別boolean
V---特殊型別void
L---物件型別(也就是引用型別)。例如 Ljava/lang/Object.
需要注意的是八種基本資料型別也有 calss,而且其對應包裝型別有一個TYPE成員變數就是其基本資料型別。特殊型別void也有class。
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
例如:
System.out.println(int.class); System.out.println(Integer.class); System.out.println(Integer.TYPE);
結果:
int
class java.lang.Integer
int
注意int不是物件,所以沒有getClass方法。只有int.class