如果你做過很多java程序,你可能對java集合類很熟悉,例如Vector和ArrayList。你可以創建一個集合并向其中增加元素:
-
- List lst = new ArrayList();
-
- lst.add(new Integer(37));
在這個特殊的范例中,一個整型值37用于構造一個Integer封裝類對象,然后那個對象被加入到列表。
這個簡單的范例展示集合的一個基礎-他們用于操縱一列對象,其中的每個對象是一個類或者接口類型。因此,一個ArrayList可以包含Object,String,Float以及Runnable類型的對象。集合類不能用于原始數據類型的列表,例如整型數組。
如果你在你的程序中使用原始類型的數組,你如何操縱它們呢?這個技巧就給你展示幾個你可以使用的技術。
第一個技術是排序。java.util.Arrays類包含一套排序和查找數組的類方法,例如:
-
- import java.util.Arrays;
-
- public class ArrayDemo1 {
- public static void main(String args[]) {
- int vec[] = {37, 47, 23, -5, 19, 56};
- Arrays.sort(vec);
- for (int i = 0; i < vec.length; i++) {
- System.out.println(vec[i]);
- }
- }
- }
這個演示程序初始化一個整數數組然后調用Arrays.sort升序排序那個數組。
類似的,你可以在排完序的數組上進行二分法查找:
-
- import java.util.Arrays;
-
- public class ArrayDemo2 {
- public static void main(String args[]) {
- int vec[] = {-5, 19, 23, 37, 47, 56};
- int slot = Arrays.binarySearch(vec, 35);
- slot = -(slot + 1);
- System.out.println("insertion point = " + slot);
- }
- }
這個程序有個微妙的概念,如果二分法查找失敗它將返回:
-(insertion point) - 1
這個演示程序以參數35調用查找方法,而那個參數在數組中不存在,方法返回值-4,如果這個值加一再取其負數就得到3,這就是35應該被插入到數組中的位置,換言之,值-5, 19和23在數組中占據的位置是0,1和2。因此值35應該在索引3的位置,而37, 47以及56順延。搜索方法并不進行實際的插入操作而只是指出應該在何處插入。
除了排序和查找,我們還可以對原始類型數組做什么?另一個有用的技術是將一個原始數組轉換為等價的對象類型數組。每個對應元素使用它們的封裝器類,例如在封裝數組中,37成為Integer(37)。
-
- import java.util.Arrays;
- import java.lang.reflect.Array;
-
- public class ArrayDemo3 {
-
- // if input is a single-dimension primitive array,
- // return a new array consisting of wrapped elements,
- // else just return input argument
-
- public static Object toArray(Object vec) {
-
- // if null, return
-
- if (vec == null) {
- return vec;
- }
-
- // if not an array or elements not primitive, return
-
- Class cls = vec.getClass();
- if (!cls.isArray()) {
- return vec;
- }
- if (!cls.getComponentType().isPrimitive()) {
- return vec;
- }
-
- // get array length and create Object output array
-
- int length = Array.getLength(vec);
- Object newvec[] = new Object[length];
-
- // wrap and copy elements
-
- for (int i = 0; i < length; i++) {
- newvec[i] = Array.get(vec, i);
- }
-
- return newvec;
- }
-
- public static void main(String args[]) {
-
- // create a primitive array
-
- int vec[] = new int[]{1, 2, 3};
-
- // wrap it
-
- Object wrappedvec[] = (Object[])toArray(vec);
-
- // display result
-
- for (int i = 0; i < wrappedvec.length; i++) {
- System.out.println(wrappedvec[i]);
- }
- }
- }
方法"toArray"的參數是一個Object對象(數組可以被賦值給一個Object引用)。如果參數是null或者代表的不是原始類型數組那么這個方法簡單的返回參數值。java.lang.Class工具類用于判斷參數是否是一個數組并獲取數組的底層元素的類型。
一旦做完這些檢查,使用java.lang.reflect.Array工具類的反射工具方法就可以獲取原始數組的長度并獲得數組的單個元素。Array.get獲得的每個元素被返回到封裝器類中,例如Integer或者Double。
最終的范例基于前面的那個并向你展示如何在數組上使用集合特性。這假設你已經有一個對象數組。
-
- import java.util.Arrays;
- import java.util.List;
-
- public class ArrayDemo4 {
- public static void main(String args[]) {
- Object vec[] = {new Integer(37), new Integer(47)};
- List lst = Arrays.asList(vec);
- lst.set(1, new Integer(57));
- for (int i = 0; i < vec.length; i++) {
- System.out.println(vec[i]);
- }
- }
- }
在這個程序中,vec是一個對象數組,包含Integer(37)和Integer(47),然后Arrays.asList被調用。它返回一個集合(List接口類型),使用數組作為集合的后臺存儲。換言之,ArrayList這樣的集合類型在它內部有某種存儲類型去存儲集合元素。在這個例子中,使用的存儲類型是作為參數傳遞到Arrays.asList的數組。這意味著集合方法所做的改變會被反射到底層的數組。
修改集合中的元素1導致底層的數組也改變,程序的輸出是:
37
57
因此如果你有一個對象數組,你可以在它上面使用集合特性,數組自身作為底層存儲。
我們也可以將集合轉換為一個對象數組,例如:
Object vec[] = lst.toArray();
package com.cucu.test;
/**
* @author http://www.linewell.com <a href=mailto:cg@linewell.com>cg@linewell.com</a>
* @version 1.0
*/
public class Sort {
public void swap(int a[], int i, int j) {
int tmp = a;
a = a[j];
a[j] = tmp;
}
public int partition(int a[], int low, int high) {
int pivot, p_pos, i;
p_pos = low;
pivot = a[p_pos];
for (i = low + 1; i <= high; i++) {
if (a > pivot) {
p_pos++;
swap(a, p_pos, i);
}
}
swap(a, low, p_pos);
return p_pos;
}
public void quicksort(int a[], int low, int high) {
int pivot;
if (low < high) {
pivot = partition(a, low, high);
quicksort(a, low, pivot - 1);
quicksort(a, pivot + 1, high);
}
}
public static void main(String args[]) {
int vec[] = new int[] { 37, 47, 23, -5, 19, 56 };
int temp;
//選擇排序法(Selection Sort)
long begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
for (int i = 0; i < vec.length; i++) {
for (int j = i; j < vec.length; j++) {
if (vec[j] > vec) {
temp = vec;
vec = vec[j];
vec[j] = temp;
}
}
}
}
long end = System.currentTimeMillis();
System.out.println("選擇法用時為:" + (end - begin));
//打印排序好的結果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
// 冒泡排序法(Bubble Sort)
begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
for (int i = 0; i < vec.length; i++) {
for (int j = i; j < vec.length - 1; j++) {
if (vec[j + 1] > vec[j]) {
temp = vec[j + 1];
vec[j + 1] = vec[j];
vec[j] = temp;
}
}
}
}
end = System.currentTimeMillis();
System.out.println("冒泡法用時為:" + (end - begin));
//打印排序好的結果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
//插入排序法(Insertion Sort)
begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
for (int i = 1; i < vec.length; i++) {
int j = i;
while (vec[j - 1] < vec) {
vec[j] = vec[j - 1];
j--;
if (j <= 0) {
break;
}
}
vec[j] = vec;
}
}
end = System.currentTimeMillis();
System.out.println("插入法用時為:" + (end - begin));
//打印排序好的結果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
//快速排序法(Quick Sort)
Sort s = new Sort();
begin = System.currentTimeMillis();
for (int k = 0; k < 1000000; k++) {
s.quicksort(vec, 0, 5);
}
end = System.currentTimeMillis();
System.out.println("快速法用時為:" + (end - begin));
//打印排序好的結果
for (int i = 0; i < vec.length; i++) {
System.out.println(vec);
}
}
}
以下是運行結果:
選擇法用時為:234
56
47
37
23
19
-5
冒泡法用時為:172
56
47
37
23
19
-5
插入法用時為:78
56
47
37
23
19
-5
快速法用時為:297
56
47
37
23
19
-5*