《Java編程思想》第四版讀書筆記 第十六章 數組

16.1 數組爲何特殊java

數組與其餘種類的容器之間的區別有三方面:效率、類型和保存基本類型的能力。在Java中數組是一種效率最高的存儲和隨機訪問對象引用序列的方式。數組就是一個簡單的線性序列,這使得元素訪問很是快速。可是爲這種速度所付出的代價是數組對象的大小被固定,而且在其生命週期中不可改變。git

泛型的出現使得容器也具有了類型檢查的能力,而自動裝箱機制使容器能夠與數組幾乎如出一轍的用於基本類型,數組的碩果僅存的優勢就是效率。算法

16.2 數組是第一級對象設計模式

在聲明數組時可採用「彙集初始化」方法:數組

int[] integers = {0, 1, 2, 3, 4};性能

可是若是不在聲明時初始化則必須採用「動態彙集初始化」方法:測試

int[] integers;優化

integers = new int[] {0, 1, 2, 3, 4};.net

16.4 多維數組設計

Java 1.5新增的Arrays.deepToString()方法能夠將多維數組轉換爲可讀的String。

數組中構造矩陣的每一個向量均可以具備任意的長度,這被稱爲粗糙數組。

自動包裝機制對數組初始化器也起做用。

練習5證實基本類型...寫錯了,應該是非基本類型

16.5 數組與泛型

不能實例化具備泛型參數類型的數組:

Peel<Banana>[] peels = new Peel<Banana>[10]; //不合法

可是能夠建立非泛型的數組,而後將其轉型爲泛型數組,一旦擁有了泛型數組的引用,就會獲得編譯器檢查。可是數組是協變的,所以List<String>也是Object[],而且能夠利用這一點把ArrayList<Integer>賦值到數組中而不會有編譯期或運行時錯誤:

List<String>[] ls;
List[] la = new List[20];
ls = (List<String>[])la;
ls[0] = new ArrayList<String>();
//編譯錯誤
//ls[1] = new ArrayList<Integer>();

Object[] objects = ls;
objects[1] = new ArrayList<Integer>();

若是肯定未來不會向上轉型,而且需求相對簡單,那麼能夠建立泛型數組。可是泛型容器老是比泛型數組更好的選擇。

16.6 建立測試數據

Java標準類庫Arrays有一個做用十分有限的fill()方法,只能用同一個值填充各個位置,針對對象而言,就是複製同一個引用進行填充,還能夠只填充數組的某個區域:

Arrays.fill(a9, "Hello");
Arrays.fill(a9, 3, 5, "World");

例子中有一段小數保留兩位小數的代碼能夠借鑑:

int trimmed = Math.round(r.nextFloat() * 100);
return ((float)trimmed) / 100;

16.7 Arrays實用功能

Java標準類庫提供static方法System.arraycopy(),用它複製數組比用for循環複製快不少。

System.arraycopy(Object src, int srcPosition, Object dest, int destPosition, int length);

基本類型數組與對象數組均可以複製。若是複製對象數組,只是複製了對象的引用——而不是對象自己的拷貝,這被稱爲淺複製。System.arraycopy()不會執行自動包裝盒自動拆包,兩個數組必須具備相同的確切類型。

Arrays類提供了靜態equals()方法,用來比較整個數組。數組相等的條件是元素個數必須相等,而且對應位置的元素也相等,經過對每個元素使用equals()方法來做比較。

使用Arrays.deepEquals()能夠比較多維數組。

使用靜態方法Arrays.sort()用語對數組進行排序。Java有兩種方式來提供比較功能:

  1. 第一種是實現java.lang.Comparable藉口,使類具備天生的比較能力。此接口只有一個compareTo()方法,此方法接收另外一個Object爲參數,若是當前對象小於參數則返回負值,若是相等則返回零,若是當前對象大於參數則返回正值。若是對沒有實現Comparable接口的類的數組進行排序,會拋出ClassCastException。由於sort()須要把參數的類型轉換爲Comparable。
  2. 假設使用別人定義好的類並無實現Comparable接口,或者類實現了Comparable接口可是須要另一種比較方式。就須要建立一個實現了Comparator接口的單獨的類。這是策略設計模式的一個應用實例。這個類有兩個方法compare()和equals()方法。不必定要實現equals()方法,由於它間接的繼承自Object的equals()方法。

Collections類包含一個reverseOrder()靜態方法能夠產生一個Comparator,它能夠翻轉天然的排序順序。

String的排序算法依據詞典編排順序排序,因此大寫字母開頭的詞都放在前面,而後是小寫字母。若是想忽略大小寫可使用String.CASE_INSENSITIVE_ORDER比較器。

Java標準類庫的排序算法對各類類型的正排序都進行了優化——針對基本類型設計的快速排序和針對對象設計的穩定歸併排序。因此無需單行排序的性能。

若是數組已經排好順序就可使用Arrays.binarySearch()執行快速查找。若是要對未排序的數組使用binarySearch()將產生不可預料的結果(可能指沒找到元素的返回狀況)。若是找到了目標,Arrays.binarySearch()產生的返回值大於或等於0.不然產生負返回值,表示若要保持數組的排序狀態此目標元素應該插入的位置。這個負值的計算方式的: -(插入點)-1。插入點指第一個大於查找對象的元素在數組中的位置,若是數組中全部的元素都小於查找的對象,插入點就等於數組的長度。若是數組包含重複的元素,則沒法保證找到的是這些副本中的哪個。

若是須要對沒有重複元素的數組排序可使用TreeSet(保持排序順序),或者LinkedHashSet(保持插入順序)。這些類會自動處理全部細節。除非他們成爲程序性能的瓶頸,不然不須要本身維護數組。

若是使用Comparator排序了某個對象數組,在使用binarySearch()時必須提供一樣的Comparator。

在編寫練習25時我犯了一個錯誤,直接使用了Arrays.asList()方法獲得的List並向其添加元素。這個方法獲得的List是長度固定的,因此當調用它的add()方法時會拋出UnsupportOperateException。

做者在本章的總結中建議,當使用新版本的Java時,優選容器而不是數組。只有在已證實性能成爲問題(而且切換到數組對性能提升有所幫助)時,才應該將程序重構爲使用數組。

我手敲的本章例子代碼和練習題代碼在https://git.oschina.net/ivanjz93/ThinkingInJava-.git 的com.ctbri.arrays和com.ctbri.util包中。

相關文章
相關標籤/搜索