1. 程式人生 > >陣列轉集合、集合轉陣列、字串陣列與int型、long型陣列等的轉換

陣列轉集合、集合轉陣列、字串陣列與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);
    }
}

 

[[email protected]

[Ljava.lang.Long;@7c23b1e1

[[email protected]

[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