[瘋狂Java]陣列:Arrays(陣列工具類)

Lirx_Tech發表於2016-05-17

1. Arrays工具類簡介:

    1) 是Java提供的專門用來運算元組的工具類,裡面有一大堆靜態方法(演算法)來運算元組,低位就相當於C++ STL的<algorithm>庫,只不過Arrays裡面全部都是運算元組的演算法,於此類似的是Collections工具類,裡面全部都是操作集合的演算法;

    2) 裡面大致分為兩類方法,一類是單線方法(用於單執行緒處理陣列),另一類是多線演算法(大多以parallel作為字首,可以充分利用現代CPU多核並行的特點多執行緒處理陣列,特別是對於那些規模非常龐大的陣列);


!!接下來介紹的全部都是Arrays工具類的static靜態工具方法;

!!所有的from - to的區間都是左閉右開的!!即[from, to);


!!單線方法:


2. 查詢:

    1) int binarySearch(type[] a, typekey);  // 在陣列a中二分查詢元素key,返回第一個找到的key的索引

    2) int binarySearch(type[] a, int fromIndex, int toIndex, typekey); // 鎖定索引範圍[from, to)內二分查詢

!!二分查詢的前提是陣列已經升序排列好了,如果key沒找到則返回-1;


3. 排序:

    1) void sort(type[] a);  // 對a升序排列

    2) void sort(type[] a, int fromIndex, int toIndex);  // 對區間[from, to)升序排列

!!Arrays的sort並沒有提供指定降序排列的引數,如果非要降序那就倒序迭代構造一個新的陣列了!


4. 相等比較:boolean equals(type[] a, type[] a2);  // 只有兩個陣列長度相等,並且每個元素也對應相等時才會返回true


!!對於排序、查詢、相等比較,如果陣列元素的型別是自定義型別則必須要實現compareTo方法可以讓這些演算法對陣列元素進行比較才行!和C++的<、==過載的道理是一樣的;


4. 拷貝:

    1) type[] copyOf(type[] original, int length); // 賦值original陣列的前length個元素形成一個新陣列返回,如果length大於original的長度,那麼多出來的部分系統自動賦予預設值(0/null);

    2) type[] copyOfRange(type[] original, int from, int to);  // 拷貝[from, to)區間,如果to超出original的長度,那麼超出部分賦予0/null;

!!除此之外,如果填拷貝的量特別巨大,則應該考慮使用作業系統的memcpy系統呼叫了,畢竟系統呼叫的記憶體填充(複製)的效率是最最高的,Java的將該系統呼叫包裝在System裡(System本身就表示OS平臺,OS的很多系統呼叫都在該類中有包裝器),其靜態方法arraycopy就是memscpy的包裝:

static native void System.arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
!意思非常明確,就是將src從srcPos開始的length長度拷貝到dest從destPos開始的位置處,其引數跟memcpy是一致的;


5. 填充:

    1) void fill(type[] a, type val);  // 整個陣列填充val

    2) void fill(type[] a, int fromIndex, int toIndex, type val); // 區間填充


6. 連綴成字串:String toString(type[] a);  // 分別呼叫各個元素的toString,將各個結果連綴成一個完整的String返回,中間用", "(逗號+空格分隔);

!!如果陣列元素是自定義型別就必須自己實現toString方法才行;


!!多線方法:都以parallel作為字首,表示平行計算


7. 排序:

    1) void parallelSort(type[] a);

    2) void parallelSort(type[] a, int fromIndex, int toIndex);


8. 二元迭代:

    1) void parallelPrefix(type[] a, int from, int to, typeBinaryOperator op);

        i. 表示將陣列a的[from, to)進行typeBinaryOperator的二元迭代;

        ii. 其中BinaryOperator就是二元操作符的意思;

        iii. 該方法的意思其實就是以下程式碼:

static void parallelPrefix(type[] a, int from, int to, TypeBinaryOperator op) {
	for (int i = from; i < to; i++) {
		type left = (i == 0)? 1: a[i - 1]; // 對於第一個元素left = 1
		type right = a[i];
		a[i] = left op right;
	}
}
!即從頭到尾逐個按照left op right的方式更新,那更新後的值繼續迭代下一個元素

        iv. 其中typeBinaryOperator表示二元運演算法,type目前基本支援Java的基礎型別(int、double等),該運演算法其實是一個函式式介面,裡面只有一個方法:

public interface TypeBinaryOperator {

    type applyAsInt(type left, type right);

}
!!例如上面的如果想使用連乘迭代那就可以直接用Lambda表示式:Arrays.parallelPrefix(arr, 1, 5, (left, right) -> left * right);就行了;

    2) 不指定區間的版本:void parallelPrefix(type[] a, typeBinaryOperator op); // 預設區間就是全部[0, length] == [0, length + 1);

!!如果是陣列[1, 2, 3, 4, 5]進行全區間的連乘迭代,得到的結果就是[1, 2, 6, 24, 120];


9. 填充:

    1) void parallelSetAll(type[] a, TypeUnaryOperator op);

    2) 該方法就是用填充演算法為陣列a的每個元素賦值;

    3) UnaryOperator是一元運算子的意思,之所以是一元是因為該方法預設用元素的索引來生成該元素的值,該介面也是一個函式式介面:

public interface TypeUnaryOperator {

    type applyAsInt(type operand); // 利用索引生成一個值,如何生成自己定義
}
    4) 該方法的意思就是:

static void parallelSetAll(Type[] a, TypeUnaryOperator op) {
	for (int i = 0; i < a.length; i++) {
		a[i] = op(i);
	}
}
    5) 例如:Arrays.parallelSetAll(a, index -> index * 5); // 一個長度為5的int陣列其填充結果就是[0, 5, 10, 15, 20]




相關文章