==================類型轉換==================
在項目中經常會遇到數組轉集合、集合轉數組、數組之間類型轉換等操作
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); } }
[J@15a6d5e1
[Ljava.lang.Long;@7c23b1e1
[I@b736a73
[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。基本類型的數組與引用類型數組也都有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); System.out.println(Integer[].class); System.out.println(int[].class); System.out.println(void.class);
結果:
int
class java.lang.Integer
int
class [Ljava.lang.Integer;
class [I
void
注意int不是對象,所以沒有getClass方法。只有int.class
==================數組與集合排序==================
JDK自帶的排序方法可以滿足大部分要求。我們知道要在集合中排序,需要使用可以排序的集合或者自己手動排序。使用可排序的集合如TreeMap,TreeSet。如果手動排序就是用Collections.sort傳入一個比較器即可。
1.數組排序
在使用Arrays.sort()對int、double、long等基本類型的數組進行排序時,只有正序排序的方法。要實現倒序排序,只有使用Integer、Double、Long等代替。
包裝類型比較的時候可以傳入比較器,如下:
import java.util.Arrays; import java.util.Collections; import java.util.Comparator; public class PlainTest { public static void main(String[] args) { // 基本數據類型Arrays.sort正序 char[] chars = { 'a', 'b', 'd', 'e', 'c', 'e', 'd', 'a' }; Arrays.sort(chars); System.out.println(chars); // 原生數組正序 Character[] characters = { 'a', 'b', 'd', 'e', 'c', 'e', 'd', 'a' }; Arrays.sort(characters); System.out.println(Arrays.toString(characters)); // 原生數組逆序 Arrays.sort(characters, Collections.reverseOrder()); System.out.println(Arrays.toString(characters)); // 自己實現逆序號排序 Arrays.sort(characters, new Comparator<Character>() { @Override public int compare(Character o1, Character o2) { if (o1 > o2) { return -1; } else if (o1 < o2) { return 1; } return 0; } }); System.out.println(Arrays.toString(characters)); } }
結果:
aabcddee
[a, a, b, c, d, d, e, e]
[e, e, d, d, c, b, a, a]
[e, e, d, d, c, b, a, a]
查看源碼:(逆序是通過反轉compare來實現的)
public static <T> Comparator<T> reverseOrder() { return (Comparator<T>) ReverseComparator.REVERSE_ORDER; } private static class ReverseComparator implements Comparator<Comparable<Object>>, Serializable { private static final long serialVersionUID = 7207038068494060240L; static final ReverseComparator REVERSE_ORDER = new ReverseComparator(); public int compare(Comparable<Object> c1, Comparable<Object> c2) { return c2.compareTo(c1); } private Object readResolve() { return reverseOrder(); } }
2.集合排序
集合排序與數組類似。
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; public class PlainTest { public static void main(String[] args) { Character[] characters = { 'a', 'b', 'd', 'e', 'c', 'e', 'd', 'a' }; List<Character> list = new ArrayList<Character>(Arrays.asList(characters)); System.out.println(list); // 集合正序 Collections.sort(list); System.out.println(list); // 集合逆序 Collections.sort(list, Collections.reverseOrder()); System.out.println(list); // 自己實現逆序號排序 Collections.sort(list, new Comparator<Character>() { @Override public int compare(Character o1, Character o2) { if (o1 > o2) { return -1; } else if (o1 < o2) { return 1; } return 0; } }); System.out.println(list); } }
結果:
[a, b, d, e, c, e, d, a]
[a, a, b, c, d, d, e, e]
[e, e, d, d, c, b, a, a]
[e, e, d, d, c, b, a, a]
