1. 程式人生 > >學習筆記2018-1-7

學習筆記2018-1-7

一、Java集合
1、Deque介面提供了一個典型的實現類: ArrayDeque,從該名稱就可以看出,它是一個基於陣列實現的雙端佇列,建立 Deque時同樣可指定一個 numElements引數,該引數用於指定 Object陣列的長度;如果不指定 numElements引數, Deque底層陣列的長度為16。
2、Set與Map之間的關係非常密切。雖然Map中放的元素是key- -value對,Set集合中放的元素是單個物件,但如果我們把key-value對中的 value當成key的附庸:key在哪裡, value就跟在哪裡。這樣就可以像對待Set一樣來對待Map了。事實上,Map提供了一個Enty內部類來封裝key-value對,而計算Enty儲存時則只考慮 Entry封裝的key.從Java原始碼來看Java是先實現了Map,然後通過包裝一個所有 value都為null的Map就實現了Set集合。
3、Hashtable和 HashMap存在兩點典型區別。Hashtable是一個執行緒安全的Map實現,但 HashMap是執行緒不安全的實現,所以 HashMap比Hashtable的效能高一點;Hashtable不允許使用null作為key和value,如果試圖把null值放進 Hashtable中,將會引發Nullpointerexception異常;但 HashMap可以使用null作為key或 value,由於 HashMap裡的key不能重複,所以 HashMap裡最多隻有一個 key-value對的key為null,但可以有無數多個 key-value對的 value為null。從 Hashtable的類名上就可以看出它是一個古老的類,它的命名甚至沒有遵守Java的命名規範:每個單詞的首字母都應該大寫。也許當初開發 Hashtable的工程師也沒有注意到這一點,後來大量Java程式中使用了 Hashtable類,所以這個類名也就不能改為Hash Table了,否則將導致大量程式需要改寫。與 Vector類似的是,儘量少用 Hashtable實現類,即使需要建立執行緒安全的Map實現類,也無須使用 Hashtable實現類,可以通過後面介紹的 Collections工具類把 HashMap變成執行緒安全的
4、如果需要使用 Weakhashmap的key來保留物件的弱引用,則不要讓該key所引物件具有任何強引用,否則將失去使用 Weakhashmap的意義
5、IdentityHashMap實現類。這個Map實現類的實現機制與 Hash Map基本相似,但它在處理兩個key相等時比較獨特:在Identity HashMap中,當且僅當兩個key嚴格相等(keyl==key2)時, Identity HashMap才認為兩個key相等:對於普通的 Hash Map而言,只要keyl和key2通過 equals方法比較返回true,且它們的 hashCode()值相等即可。
6、Java提供了一個操作Set、List和Map等集合的工具類: Collections,該工具類裡提供了大量方法對集合元素進行排序、查詢和修改等操作,還提供了將集合物件設定為不可變、對集合物件實現同步控制等方法。
6.1、排序操作
Collections提供瞭如下幾個方法用於對List集合元素進行排序。

static void reverse( List list):反轉指定List集合中元素的順序
static void shuffle( List list)):對List集合元素進行隨機排序( (shuffle方法模擬了“洗牌”動作)。
static void sort(List list):根據元素的自然順序對指定List集合的元素按升序進行排序。static void sort(List list,. Comparator c):根據指定 Comparator產生的順序對List集合元素進行排序
static void swap( List list,inti,intj):將指定List集合中的i處元素和j處元素進行交換
static void rotate( List list, int distance):當 distance為正數時,將list集合的後 i distance個元素“整體”移到前面;當 distance為負數時,將lit集合的前 distance個元素“整體”移到後面。該方法不會改變集合的長度。

二、類、物件和介面
1、對於只有一個抽象方法的介面,需要這種介面的物件時,就可以提供一個 lambda表示式。這種介面稱為函式式介面( functional interface)
■註釋:你可能想知道為什麼函式式介面必須有一個抽象方法。不是介面中的所有方法都是抽象的嗎?實際上,介面完全有可能重新宣告 Object類的方法,如 to String或 clone這些宣告有可能會讓方法不再是抽象的。( Java API中的一些介面會重新宣告 Object方法來附加 javadoc註釋。 Comparator API就是這樣一個例子。)更重要的是,正如6.1.5節所述,在 Java SE8中,介面可以宣告非抽象方法。
2、如果設計你自己的介面,其中只有一個抽象方法,可以用 Functionallnterface 註解來標記這個介面。這樣做有兩個優點。如果你無意中增加了另一個非抽象方法,編譯器會產生一個錯誤訊息。另外 Javadoc頁裡會指出你的介面是一個函式式介面。並不是必須使用註解。根據定義,任何有一個抽象方法的介面都是函式式介面。不過使用@ Functionallnterface註解確實是一個很好的做法。

3、內部類中宣告的所有靜態域都必須是final。原因很簡單,我們希望一個靜態域只有一個例項,不過對於每個外部物件,會分別有一個單獨的內部類例項。如果這個域不是 final,它可能就不是唯一的。
4、內部類不能有 static方法。Java語言規範對這個限制沒有做任何解釋。其實也可以允許有靜態方法,限制只能訪問外圍類的靜態域和方法就好。顯然,Java設計者認為相對於這種複雜性來說,它帶來的好處有些得不償失。
5、初始化塊。前面已經講過兩種初始化資料域的方法:
·在構造器中設定值
·在宣告中賦值
實際上,Java還有第三種機制,稱為初始化塊( (initialization block)。在一個類的宣告中,可以包含多個程式碼塊。只要構造類的物件,這些塊就會被執行。例如,
class Employee{
static int nextid
String name
Double salary:
∥/object block

{
id++
}
public Employee(String n, double s)
{
nane n,
salary s:
}
}
在這個示例中,無論使用哪個構造器構造物件,id域都在物件初始化塊中被初始化。首先執行初始化塊,然後才執行構造器的主體部分。這種機制不是必需的,也不常見。通常會直接將初始化程式碼放在構造器中。有時會在面試中見到這種用法:
例如:下面的技巧稱為“雙括號初始化”( double brace initialization),這裡利用了內部類語法。ArrayList list = new ArrayList<>(){{add(“1”);add(“2”)}}等同於
ArrayList list = new ArrayList<>();
list.add(“1”);
list.add(“2”);
6、建立一個與超類大體類似(但不完全相同)的匿名子類通常會很方便。不過,對於 equals方法要特別當心。第5章中,我們曾建議 equals方法最好使用以下測試: if ( i==other)return false;但是對匿名子類做這個測試時會失敗。
7、生成日誌或除錯訊息時,通常希望包含當前類的類名,如:System.err.println("Something happened in"+getclass());不過,這對於靜態方法不奏效。畢竟,呼叫 getclass時呼叫的是 this.,而靜態方法沒有this。所以應該使用以下表達式:new Object(){}.getClass().getEnclosingClass()// gets class of static method
在這裡, new會建立 Object的一個匿名子類的一個匿名物件, getEnclosingClass()則得到其外圍類,也就是包含這個靜態方法的類。