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有兩種方式來提供比較功能:
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包中。