JAVA陣列與容器類別主要有三個方面的差異:效率、類型和保存基本類型的能力。在JAVA中,陣列是一種效率最高的儲存和隨機存取物件引用序列的方式。數組就是一個簡單的線性數組,這使得元素存取非常快速。但是為此付出的代價卻是數組的大小被固定,並且在其生命週期中不可改變。
由於範型和自動包裝機制的出現,容器已經可以與陣列幾乎一樣方便地用於基本類型中了。陣列和容器都可以一定程度上防止你濫用他們,如果越界,就會得到RuntimeException異常。數組碩果僅存的優勢便是效率,然而,如果要解決更一般化的問題,那數組可能會受到過多的限制,因此這種情況下大部分還是會選擇容器。
因此,如果使用最近的JAVA版本,應該優先選擇容器而不是陣列。只有在已證明效能已成為問題,並且切換到陣列可以提高效能時,才應該重構程式為陣列。
【初始化】
JAVA對數組初始化有很嚴格的規定,這樣可以有效地防止濫用數組。如果初始化錯誤,會直接得到CompileException而不是RuntimeException。在未對數組正確初始化之前,無法用此數組引用做任何事情。
陣列定義有int[] array 和int array[],一般採用第一種風格,可以將型別與變數名稱分開。
數組的初始化有兩種方式,靜態初始化和動態初始化。初始化的時候必須指定長度,多維數組第一維的長度必須指出,同時必須由高維向低維定義。初始化動作可以在程式碼的任何地方,而用{}方式只能在建立陣列的地方出現。具體初始化方式見程序:
arrayA = new int[10]; //動態初始化
System.out.println("arrayA length: " + arrayA.length);
int[] arrayC = new int[]{1,2,3,4};
System.out.println("arrayC length: " + arrayC.length);
//int[] arrayD = new int[1]{1}; //錯誤的初始化,不能同時定義維和初始化值
int[][] arrayE = new int[1][];
System.out.println("arrayE length: " + arrayE.length);
//int[][] arrayF = new int[][2]; //應先指定高維度的長度
int[][] arrayG = new int[][]{{1,2,3,4},{5,6,7},{7,24,23,24}};
System.out.println("arrayG length: " + arrayG.length);
int[][][] arrayH = new int[][][]{{{1,2,3},{4,5,6},{7,8,9},{10,11,12} }};
System.out.println("arrayH length: " + arrayH.length);
dummyArray[] arrayI = {new dummyArray(),new dummyArray()}; //自訂陣列類型
System.out.println("arrayI length: " + arrayI.length);
System.out.println("arrayI[1]: " + arrayI[1].getValue());
dummyArray[] arrayK = new dummyArray[5];
System.out.println("arrayK[0]: " + arrayK[0]); //null
for(int i = 0; i < arrayK.length; i++){
arrayK[i] = new dummyArray();
}
System.out.println("arrayK[0]: " + arrayK[0].getValue()); //2
}
}
class dummyArray{
private static int temp;
private final int arrayValue = temp++;
public int getValue(){
return arrayValue;
}
}
輸出:
arrayB length: 5
arrayA length: 10
arrayC length: 4
arrayE length: 1
arrayG length: 3
arrayH length: 1
arrayI length: 2
arrayI[1]: 1
arrayK[0]: null
arrayK[0]: 2
int[][] arrayB = new int[10][];
System.out.println("arrayB length: " + arrayB.length);
int[][] arrayC = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7} ,};//注意後面的逗號
System.out.println("arrayC length: " + arrayC.length);
int[][] arrayD = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7} ,{}};
System.out.println("arrayD length: " + arrayD.length);
}
}
輸出:
arrayA length: 15
arrayB length: 10
arrayC length: 3
arrayD length: 4
【賦值與引用】
JAVA數組初始化的時候擁有的只是對數組的引用,並沒有給數組分配儲存空間。因此,數組之間的複製不能簡單地用“=”賦值,因為操作的是同一物件。如下程序:
}
}
輸出:
I'm testA,I have no changed:testA
I'm arrayA, I have no changed:arrayB have changed
【數組複製】
JAVA中複製數組的方法:
1.使用FOR循環複製全部或指定元素,效率較低
2.使用clone方法,得到數組的值,而不是引用。然而clone不能複製指定元素,靈活性較低
3.使用System.arraycopy(src, srcPos, dest, destPos, length)方法,java標準類別庫提供有static方法System.arraycopy(),用它複製數組要比for循環快很多,System.arraycopy()針對所有型別做了重載,基本型別數組和物件數組都可以用System.arraycopy()複製,但是物件數組只是複製引用,不會出現兩份物件的拷貝。這被稱為淺複製(shallowcopy)。
src:來源數組;
srcPos:來源陣列要複製的起始位置;
dest:目的數組;
destPos:目的數組放置的起始位置;
length:複製的長度.
注意:System.arraycopy()不會進行自動包裝和自動拆包,因此兩個陣列必須是相同類型或可以轉換為相同類型的陣列。同時,這個方法也可以用來複製陣列本身。
int[] test ={0,1,2,3,4,5,6};
System.arraycopy(test,0,test,3,3);
則結果為:{0,1,2,0,1,2,6};
測試程序如下:
//clone方法
int[] arrayB = new int[9];
arrayB = array.clone();
//測試
arrayB[1] = 19;
for(int i = 0; i < arrayB.length; i++){
System.out.print(arrayB[i] + ",");
}
System.out.println("");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + ",");
}
System.out.println("");
//System.arrayCopy 方法
int[] arrayC = new int[9];
System.arraycopy(array, 0, arrayC, 0, arrayC.length);
//測試
arrayC[1] = 19;
for(int i = 0; i < arrayC.length; i++){
System.out.print(arrayC[i] + ",");
}
System.out.println("");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + ",");
}
}
}
String[][] arrayD = {{"a","b"},{"c","d"}};
String[][] arrayE = {{"a","b"},{"c","d"}};
System.out.println(Arrays.deepEquals(arrayD, arrayE));
}
}
【返回數組】
C和C++不能傳回一個數組,只能傳回指向數組的指針,因為傳回數組使得控制數組的生命週期變得困難,並且容易造成記憶體洩漏。 java允許直接傳回一個數組,並且可以由垃圾回收機制回收。
【數組與容器轉換】【無法轉換基本類型數組】
數組轉為List:
int[] arrayB = {1,2,3};
List listB = java.util.Arrays.asList(arrayB);
System.out.println("listB: " + listB);
Integer[] arrayC = {1,2,3};
List listC = java.util.Arrays.asList(arrayC);
System.out.println("listC: " + listC);
}
}
輸出:
listA: [a, b, c]
listB: [[I@de6ced]
listC: [1, 2, 3]
List轉為數組
String[] strings = new String[list.size()];
array = list.toArray(strings);
for(int i = 0, j = array.length; i < j; i++){
System.out.print(array[i] + ",");
}
}
}
輸出為:
list: [testA, testB, testC]
testA,testB,testC
public static String[] arrayUnique(String[] array){
List<String> list = new ArrayList<String>();
for(int i = 0, j = array.length; i < j; i++){
if(!list.contains(array[i])){
list.add(array[i]);
}
}
String[] strings = new String[list.size()];
String[] arrayUnique = list.toArray(strings);
return arrayUnique;
}
}
Double[] arrayB = new Double[1000000];
for(int i = 0, j = arrayB.length; i < j; i++){
arrayB[i] = Math.ceil(Math.random()*1000);
}
System.out.println("start");
long startTime = System.currentTimeMillis();
arrayUnique(array);
long endTime = System.currentTimeMillis();
System.out.println("array unique run time: " +(endTime - startTime) +"ms");
long startTimeB = System.currentTimeMillis();
arrayUnique(arrayB);
long endTimeB = System.currentTimeMillis();
System.out.println("arrayB unique run time: " +(endTimeB - startTimeB) +"ms");
}
public static Double[] arrayUnique(Double[] array){
List<Double> list = new ArrayList<Double>();
for(int i = 0, j = array.length; i < j; i++){
if(!list.contains(array[i])){
list.add(array[i]);
}
}
Double[] doubles = new Double[list.size()];
Double[] arrayUnique = list.toArray(doubles);
return arrayUnique;
}
}
輸出:
start
array unique run time: 577ms
arrayB unique run time: 5663ms