《Thinking in Java》學習——16章數組

數組為什么這么特殊

1.數組與其他容器之間的區(qū)別有三個方面:效率、類型和保存基本類型的能力。在Java中,數組是一種效率最高的存儲和隨機訪問對象引用序列的方式。數組就是一個簡單的線性序列,這使得元素的訪問非常快速。但是為這種速度所付出的 代價是數組對象大小被固定,并且在其生命周期中不可改變。
2.隨著自動包裝機制的出現,容器已經能與數組幾乎一樣方便地用于基本類型中了。數組僅存的優(yōu)點就是效率。然而,如果要解決更加一般化的問題,那數組就可能收到過多的限制,因此在這些情況下還是會使用容器。

數組是第一級對象

1.數組的制度成員length是數組對象的一部分,表示此數組對象可以存儲多少元素,也就是說,length是數組的大小,而不是實際保存的元素。因此通過length詢問數組的大小有一個缺點:你無法知道數組中確切地有多少個元素。
2.新生成一個數組對象時,其中所有的引用被自動初始化為null,所以檢查其中引用是否為null,即可知道數組的某個位置是否存有對象。同樣的,如果數組中的對象是基本類型,就會被自動初始化為相應的值。

返回一個數組

1.假設要寫一個方法,而且希望它返回不止一個值,而是一組值。在Java中只需要直接“返回一個數組”,無需對數組負責——只要需要它,它就會一直存在,當使用完之后,垃圾回收器會清理掉它。

多維數組

1.Java SE5中的Arrays.deepToString()方法,可以將多維數組轉換為多個String

public class ThreeDWithNew {
    public static void main(String... args) {
        int[][][] a = new int[2][2][4];
        System.out.println(Arrays.deepToString(a));
    }
}
/* Output:
[[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0]]]
*/

2.數組中構成矩陣的每個向量都可以具有任意長度(這被稱為粗糙數組)。

數組與泛型

1.通常數組與泛型不能很好地結合。你不能實例化具有參數化類型的數組。擦除會移除參數類型信息,而數組必須知道它們所持有的確切類型,以強制保證類型安全。
2.可以參數化數組本身的類型:

public  <T> T[] f(T[] arg) {
    return arg;
}

3.編譯器確實不能讓你實例化泛型數組,但是,它允許你創(chuàng)建對這種數組的引用:

List<String>[] ls; //Success
ls = new ArrayList<String>[10]; //Illegal

盡管不能創(chuàng)建實際的持有泛型的數組對象,但是你可以創(chuàng)建非泛型的數組,然后將其轉型:

public class ArrayOfGenerics {
    @SupressWarning("unchecked")
    public static void main(String... args) {
        List<String> ls;
        List[] la = new List[10];
        ls = (List<String>[]) la; //unchecked warning
        ls[0] = new ArrayList<String>();
    }
}

問題是數組是協變類型的,因此List<String>[]也是一個Object[],并且你可以利用這一點,將一個ArrayList<Integer>賦值到你的數組中,而不會有任何編譯期或運行時錯誤。

創(chuàng)建測試數據

一.Arrays.fill()

Java標準類庫Arrays有一個作用十分有限的fill()方法:只能用同一個值填充哥哥位置,針對對象而言就是膚質同一個引用進行填充:

int[] a = new int[6];
Arrays.fill(a, 11);

String[] s = new String[6];
Arrays.fill(s, 3, 5,  "Hello");

使用Arrays.fill()可以填充整個數組,或者只填充數組的某個區(qū)域。但是由于只能用單一的數值來調用Arrays.fill(),因此所產生的結果并非特別有用。

二.數據生成器

1.為了以靈活的方式創(chuàng)建更有意義的數組,我們可以引用Generator的概念。如果某個工具使用了Generator,那么久就可以通過選擇Generator的類型來創(chuàng)建任何類型的數據。

Arrays實用功能

一.復制數組

1.Java標準類庫提供有static方法System.arraycopy(),用它復制數組比用for循環(huán)要快得多。System.arraycopy()針對所有類型做了重載:

int[] i = new int[7];
int[] j = new int[5];
Arrays.fill(j, 100);
System.arraycopy(i, 0, j, 0, j.length);

arraycopy()需要的參數有:源數組,表示從源數組中的什么位置開始復制的偏移量,表示從目標數組的什么位置開始復制的偏移量,以及需要復制的元素個數。注意避免數組越界操作。
2.System.arraycopy()不會執(zhí)行自動包裝和自動拆包。

二.數組的比較

1.Arrays類提供了重載后的equals()方法,用來比較整個數組。數組相等的條件是元素個數必須相等,并且對應位置的元素也相等,這可以通過對每一個元素使用equals()作比較來判斷:

int[] a1 = new int[10];
int[] a2 = new int[10];
Arrays.fill(a1, 10);
Arrays.fill(a2, 10);
print(Arrays.equals(a1, a2)); //Output : true
三.數組元素的比較

1.Java有兩種方式來提供比較功能,第一種是實現java.lang.Comparable接口,并實現compareTo()方法,使你的類具有天生的比較能力。第二種是創(chuàng)建一個實現了Comparator接口的類,實現compare()方法,有特殊需要時重寫equals()方法。

四.數組排序

1.使用內置的排序方法,就可以對任意的基本類型數組進行排序;也可以對人意的對象數組進行排序,只要該對象實現了Comparable接口或具有相關聯的Comparator

String[] sa = {"Java", "C++", "Python"};
Arrays.sort(sa);

Java標準類庫中的排序算法針對正排序的特殊類型進行了優(yōu)化——針對基本類型設計的“快速排序”,以及針對對象設計的“穩(wěn)定歸并排序”。所以無須擔心排序的性能。

五.在已排序的數組中查找

1.如果數組已經排好序了,就可以使用Arrays.binarySearch()執(zhí)行快速查找。如果要對味排序的數組使用,那么就會產生不可預料的結果:

int[] a = {1, 2, 3, 4, 5};
Arrays.sort(a);
int position = Arrays.binarySearch(a, 3);

2.如果找到了目標,Arrays.binarySearch()產生的返回值等于或大于0.否則,它產生負返回值,表示若要保持數組的排序狀態(tài)此目標元素所應該插入的位置。這個負值的計算方式為:
- (插入點) - 1
插入點是指,第一個大雨查找對象的元素在數組中的位置。
3.搜索算法不是專為包含重復元素的數組而設計的,雖然仍可用,但是無法保證找到的是這些副本中的哪一個。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容