優化背景
有些場景下(比如入參要求)需要將集合(比如List)轉為陣列型別,利用集合的toArray方法應該最為方便的,對於toArray()無參方法其返回的是Object[],強制轉其他型別陣列會ClassCastException。推薦使用帶引數的toArray(T[]),不過使用上需要注意
list強轉陣列拋異常-ClassCastException
@Test
//list強轉陣列拋異常-ClassCastException
public void arrayError(){
List<String> listToArray = new ArrayList<>();
listToArray.add("jav");
listToArray.add(0, "python");
listToArray.add("php");
listToArray.add("c#");
String[] str = (String[]) listToArray.toArray();
System.out.println(str);
}
異常資訊列印:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
- 對於toArray()無參方法其返回的是Object[],正確寫法
@Test
//list轉陣列,使用object物件接受再迴圈遍歷轉出
public void arrayObject(){
List<String> listToArray = new ArrayList<>();
listToArray.add("jav");
listToArray.add(0, "python");
listToArray.add("php");
listToArray.add("c#");
String[] s = new String[listToArray.size()];
Object[] o = listToArray.toArray();
for (int i = 0; i < o.length; i++) {
s[i] = o[i].toString();
}
System.out.println(Arrays.toString(s));
}
輸出:[python, java, php, c#]
- 另外 T[] toArray(T[] a);
- 解決方案:https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#toArray-T:A-
輸入引數為對應型別陣列,那麼應該建立多大的陣列作為引數呢,推薦為0,例如我們的有一個List包含100w的資料
toArray(new String[0]), 建立一個大小為0的陣列,當為輸入陣列長度小於集合size時,toArray方法會自動建立一個等大陣列放入資料並返回。
toArray(new String[100000]),同上輸入的10w陣列比集合size小,toArray方法會重新建立一個等大陣列放入資料並返回,原來的10w陣列等於白建了
toArray(new String[1000000]),輸入陣列長度與集合size相等,當是一個理想狀態時,即陣列size沒有發生變化(比如沒有併發情況),那麼toArray方法會直接使用輸入陣列並返回,但如果在輸入陣列建立之後,原集合size發生了變化,最糟糕的情況會退化為#2
toArray(new String[2000000]),輸入陣列長度大於集合size,那麼toArray方法會直接使用輸入陣列並返回,當然多出去的那部分陣列量就算浪費了
- 最優化寫法
@Test
//list轉陣列-最優化寫法
public void OptimizeCode(){
List<String> listToArray = new ArrayList<>();
listToArray.add("jav");
listToArray.add(0, "python");
listToArray.add("php");
listToArray.add("c#");
String[] str = listToArray.toArray(new String[0]);
System.out.println(Arrays.toString(str));
}
輸出:[python, java, php, c#]
- 由此可以看出,如果在沒有特殊需要的情況下,使用#1是比較高效的,也是大多數情況下比較推薦的寫法