ArrayList實現原理要點概括
參考文獻:
http://zhangshixi.iteye.com/blog/674856l
https://www.cnblogs.com/leesf456/p/5308358.html
- ArrayList是List接口的可變數組非同步實現,并允許包括null在內的所有元素。
- 底層使用數組實現
- 該集合是可變長度數組,數組擴容時,會將老數組中的元素重新拷貝一份到新的數組中,每次數組容量增長大約是其容量的1.5倍,這種操作的代價很高。
- 采用了Fail-Fast機制,面對并發的修改時,迭代器很快就會完全失敗,而不是冒著在將來某個不確定時間發生任意不確定行為的風險
- remove方法會讓下標到數組末尾的元素向前移動一個單位,并把最后一位的值置空,方便GC
LinkedList實現原理要點概括
參考文獻:
1.http://www.cnblogs.com/ITtangtang/p/3948610.htmll
2.https://www.cnblogs.com/leesf456/p/5308843.html
- LinkedList是List接口的雙向鏈表非同步實現,并允許包括null在內的所有元素。
- 底層的數據結構是基于雙向鏈表的,該數據結構我們稱為節點
- 雙向鏈表節點對應的類Node的實例,Node中包含成員變量:prev,next,item。其中,prev是該節點的上一個節點,next是該節點的下一個節點,item是該節點所包含的值。
- 它的查找是分兩半查找,先判斷index是在鏈表的哪一半,然后再去對應區域查找,這樣最多只要遍歷鏈表的一半節點即可找到
HashMap實現原理要點概括
參考文獻:http://zhangshixi.iteye.com/blog/672697
參考文獻:http://blog.csdn.net/lizhongkaide/article/details/50595719
- HashMap是基于哈希表的Map接口的非同步實現,允許使用null值和null鍵,但不保證映射的順序。
- 底層使用數組實現,數組中每一項是個單向鏈表,即數組和鏈表的結合體;當鏈表長度大于一定閾值時,鏈表轉換為紅黑樹,這樣減少鏈表查詢時間。
- HashMap在底層將key-value當成一個整體進行處理,這個整體就是一個Node對象。HashMap底層采用一個Node[]數組來保存所有的key-value對,當需要存儲一個Node對象時,會根據key的hash算法來決定其在數組中的存儲位置,在根據equals方法決定其在該數組位置上的鏈表中的存儲位置;當需要取出一個Node時,也會根據key的hash算法找到其在數組中的存儲位置,再根據equals方法從該位置上的鏈表中取出該Node。
- HashMap進行數組擴容需要重新計算擴容后每個元素在數組中的位置,很耗性能
- 采用了Fail-Fast機制,通過一個modCount值記錄修改次數,對HashMap內容的修改都將增加這個值。迭代器初始化過程中會將這個值賦給迭代器的expectedModCount,在迭代過程中,判斷modCount跟expectedModCount是否相等,如果不相等就表示已經有其他線程修改了Map,馬上拋出異常
Hashtable實現原理要點概括
參考文獻:http://blog.csdn.net/zheng0518/article/details/42199477
- Hashtable是基于哈希表的Map接口的同步實現,不允許使用null值和null鍵
- ** 底層使用數組實現,數組中每一項是個單鏈表,即數組和鏈表的結合體**
- Hashtable在底層將key-value當成一個整體進行處理,這個整體就是一個Entry對象。Hashtable底層采用一個Entry[]數組來保存所有的key-value對,當需要存儲一個Entry對象時,會根據key的hash算法來決定其在數組中的存儲位置,在根據equals方法決定其在該數組位置上的鏈表中的存儲位置;當需要取出一個Entry時,也會根據key的hash算法找到其在數組中的存儲位置,再根據equals方法從該位置上的鏈表中取出該Entry。
- synchronized是針對整張Hash表的,即每次鎖住整張表讓線程獨占
ConcurrentHashMap實現原理要點概括
參考文獻:http://blog.csdn.net/zheng0518/article/details/42199477
- ConcurrentHashMap允許多個修改操作并發進行,其關鍵在于使用了鎖分離技術。
- 它使用了多個鎖來控制對hash表的不同段進行的修改,每個段其實就是一個小的hashtable,它們有自己的鎖。只要多個并發發生在不同的段上,它們就可以并發進行。
- ConcurrentHashMap在底層將key-value當成一個整體進行處理,這個整體就是一個Entry對象。Hashtable底層采用一個Entry[]數組來保存所有的key-value對,當需要存儲一個Entry對象時,會根據key的hash算法來決定其在數組中的存儲位置,在根據equals方法決定其在該數組位置上的鏈表中的存儲位置;當需要取出一個Entry時,也會根據key的hash算法找到其在數組中的存儲位置,再根據equals方法從該位置上的鏈表中取出該Entry。
- 與HashMap不同的是,ConcurrentHashMap使用多個子Hash表,也就是段(Segment)
- ConcurrentHashMap完全允許多個讀操作并發進行,讀操作并不需要加鎖。如果使用傳統的技術,如HashMap中的實現,如果允許可以在hash鏈的中間添加或刪除元素,讀操作不加鎖將得到不一致的數據。ConcurrentHashMap實現技術是保證HashEntry幾乎是不可變的。
HashSet實現原理要點概括
參考文獻:http://zhangshixi.iteye.com/blog/673143l
- HashSet由哈希表(實際上是一個HashMap實例)支持,不保證set的迭代順序,并允許使用null元素。
- 基于HashMap實現,API也是對HashMap的行為進行了封裝,可參考HashMap
LinkedHashMap實現原理要點概括
參考文獻:http://zhangshixi.iteye.com/blog/673789l
- LinkedHashMap繼承于HashMap,底層使用哈希表和雙向鏈表來保存所有元素,并且它是非同步,允許使用null值和null鍵。
- 基本操作與父類HashMap相似,通過重寫HashMap相關方法,重新定義了數組中保存的元素Entry,來實現自己的鏈接列表特性。該Entry除了保存當前對象的引用外,還保存了其上一個元素before和下一個元素after的引用,從而構成了雙向鏈接列表。
LinkedHashSet實現原理要點概括
參考文獻:http://zhangshixi.iteye.com/blog/673319l
- 對于LinkedHashSet而言,它繼承與HashSet、又基于LinkedHashMap來實現的。LinkedHashSet底層使用LinkedHashMap來保存所有元素,它繼承與HashSet,其所有的方法操作上又與HashSet相同。
什么是Java集合API
Java集合框架API是用來表示和操作集合的統一框架,它包含接口、實現類、以及幫助程序員完成一些編程的算法。簡言之,API在上層完成以下幾件事:
● 編程更加省力,提高城程序速度和代碼質量
● 非關聯的API提高互操作性
● 節省學習使用新API成本
● 節省設計新API的時間
● 鼓勵、促進軟件重用
具體來說,有6個集合接口,最基本的是Collection接口,由三個接口Set、List、SortedSet繼承,另外兩個接口是Map、SortedMap,這兩個接口不繼承Collection,表示映射而不是真正的集合。
Collection接口:存儲一組不唯一,無序的對象
List接口:存儲一組不唯一,有序的對象
Set接口:存儲一組唯一,無序的對象
Map接口:存儲一組鍵值對象,提高鍵(key)到值(value)的映射
為何Map接口不繼承Collection接口?
雖然Map接口和它的實現也是集合框架的一部分。但Map不是集合。集合也不是Map。
因此,Map繼承Collection毫無意義,反之亦然。
假設Map繼承Collection接口,那么元素去哪兒?Map包括key-value對,它提供抽取key或value列表集合的方法,可是它不適合“一組對象”規范
2.HashMap和Hashtable之間的區別?
在JDK1.6,JDK1.7中,HashMap采用位桶+鏈表實現,即使用鏈表處理沖突,同一hash值的鏈表都存儲在一個鏈表里。但是當位于一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查找的效率較低。而JDK1.8中,HashMap采用位桶+鏈表+紅黑樹實現,當鏈表長度超過閾值(8)時,將鏈表轉換為紅黑樹,這樣大大減少了查找時間。
1.兩者最主要的區別在于Hashtable是線程安全,而HashMap則非線程安全
Hashtable的實現方法里面都添加了synchronized關鍵字來確保線程同步,因此相對而言HashMap性能會高一些,我們平時使用時若無特殊需求建議使用HashMap,在多線程環境下若使用HashMap需要使用Collections.synchronizedMap()方法來獲取一個線程安全的集合。
2.HashMap可以使用null作為key,而Hashtable則不允許null作為key
雖說HashMap支持null值作為key,不過建議還是盡量避免這樣使用,因為一旦不小心使用了,若因此引發一些問題,排查起來很是費事
3.HashMap是對Map接口的實現,HashTable實現了Map接口和Dictionary抽象類
HashMap的初始容量為16,Hashtable初始容量為11,兩者的填充因子默認都是0.75
4.HashMap擴容時是當前容量翻倍即:capacity2,Hashtable擴容時是容量翻倍+1即:capacity2+1
5.兩者計算hash的方法不同
Hashtable計算hash是直接使用key的hashcode對table數組的長度直接進行取模
Iterator、ListIterator 和 Enumeration的區別?
Enumeration接口在Java1.2版本開始有,所以Enumeration是合法規范的接口
Enumeration使用elements()方法
Iterator對所有Java集合類都有實現
Iterator使用iterator方法
Iterator只能往一個方向前進
ListIterator僅僅對List類型的類實現了
ListIterator使用listIterator()方法
fail-fast 與 fail-safe 之間的區別?
Fail fast快速地報告任何的failure。無論何時任何一個問題都會引發 fail fast系統fails
在Java Fail fast 迭代器中,迭代objects集合有時會出現并發修改異常,出現這種情況有2個原因
如果一個線程正在迭代一個集合,而另一個線程同時試圖修改這個集合
在調用remove()方法后,如何我們還試圖去修改集合object
Java 中 Set 與 List 有什么不同?
Set是一個不允許重復元素存在的集合
Set沒有索引
Set僅僅允許一個null值
Set有類:HashSet、LinkedHashMap、TreeSet
List有索引
List允許N個null值
List可以按插入順序顯示
List有類:Vector、ArrayList、LinkedList
arraylist 與 vector 的區別?
Vector 在Java的第一個版本就引入了,也就是說vector是一個合法規范的類
ArrayList在Java1.2版本引入的,是Java 集合框架的組成部分
Vector是同步的
ArrayList是不同步的
什么類實現了List接口?
ArrayList
LinkedList
Vector
什么類實現了Set接口?
HashSet
LinkedHashSet
TreeSet
如何保證一個集合線程安全?
Vector, Hashtable, Properties 和 Stack 都是同步的類,所以它們都線程安全的,可以被使用在多線程環境中
使用Collections.synchronizedList(list)) 方法,可以保證list類是線程安全的
使用java.util.Collections.synchronizedSet()方法可以保證set類是線程安全的
是否可以往 TreeSet 或者 HashSet 中添加 null
可以往 hashset 中添加一個 null
TreeSet 也允許一個 null值
Iterator符合哪個設計模式?
Iterator 設計模式
如何對Object的list排序?
對objects數組進行排序,我們可以用Arrays.sort()方法
如果要對objects的集合進行排序,需要使用Collections.sort()方法
HashSet 實現了哪個數據結構?
HashSet 內部實現了hashmap
為什么 Collection 不能繼承 Cloneable 和 Serializable?
Collection接口指定一組對象,對象即為它的元素。怎樣維護這些元素由Collection的詳細實現決定。
比如。一些如List的Collection實現同意反復的元素。而其他的如Set就不同意。非常多Collection實現有一個公有的clone方法。
然而。把它放到集合的全部實現中也是沒有意義的。這是由于Collection是一個抽象表現。重要的是實現。
當與詳細實現打交道的時候,克隆或序列化的語義和含義才發揮作用。所以,詳細實現應該決定怎樣對它進行克隆或序列化,或它能否夠被克隆或序列化。
在全部的實現中授權克隆和序列化,終于導致更少的靈活性和很多其他的限制。特定的實現應該決定它能否夠被克隆和序列化。
hashCode() 和 equals() 方法的重要性?如何在Java中使用它們?
hashCode() 和 equals() 方法定義在”object”類中
如果equals() 方法在比較2個對象時返回true,那么hashCode()的返回值必須得一樣
什么是 Properties 類?
Properties 是Hashtable的子類。它被用于維護值的list,其中它們的鍵、值都是String類型
如何將一個字符串轉換為arraylist?
使用 arrayList.toArray() 方法
Java 集合類框架的基本接口有哪些?
Java 集合類提供了一套設計良好的支持對一組對象進行操作的接口和類。Java 集合類里面最基本的接口有:
Collection:代表一組對象,每一個對象都是它的子元素。
Set:不包含重復元素的 Collection。
List:有順序的 collection,并且可以包含重復元素。
Map:可以把鍵(key)映射到值(value)的對象,鍵不能重復。
為什么集合類沒有實現 Cloneable 和 Serializable 接口?
集合類接口指定了一組叫做元素的對象。集合類接口的每一種具體的實現類都可以選擇以它自己的方式對元素進行保存和排序。有的集合類允許重復的鍵,有些不允許。
什么是迭代器(Iterator)?
Iterator 接口提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器實例的 迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素。
克隆(cloning)或者是序列化(serialization)的語義和含義是跟具體的實現相關的。因此,應該由集合類的具體實現來決定如何被克隆或者是序列化。
Iterator 和 ListIterator 的區別是什么?
下面列出了他們的區別:
Iterator 可用來遍歷 Set 和 List 集合,但是 ListIterator 只能用來遍歷 List。
Iterator 對集合只能是前向遍歷,ListIterator 既可以前向也可以后向。
ListIterator 實現了 Iterator 接口,并包含其他的功能,比如:增加元素,替換元素,獲取前一個和后一個元素的索引,等等。
快速失敗(fail-fast)和安全失敗(fail-safe)的區別是什么?
Iterator 的安全失敗是基于對底層集合做拷貝,因此,它不受源集合上修改的影響。java.util包下面的所有的集合類都是快速失敗的,而 java.util.concurrent 包下面的所有的類都是安全 失敗的。快速失敗的迭代器會拋出 ConcurrentModificationException 異常,而安全失敗的迭 代器永遠不會拋出這樣的異常。
Java 中的 HashMap 的工作原理是什么?
Java 中的 HashMap 是以鍵值對(key-value)的形式存儲元素的。HashMap 需要一個 hash 函數,它使用 hashCode()和 equals()方法來向集合/從集合添加和檢索元素。當調用 put()方法的時候,HashMap 會計算 key 的 hash 值,然后把鍵值對存儲在集合中合適的索引上。如果 key已經存在了,value 會被更新成新值。HashMap 的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。
hashCode()和 equals()方法的重要性體現在什么地方?
Java 中的 HashMap 使用 hashCode()和 equals()方法來確定鍵值對的索引,當根據鍵獲取值
以這兩個方法的實現對 HashMap 的精確性和正確性是至關重要的
HashMap 和 Hashtable 有什么區別?
HashMap 和 Hashtable 都實現了 Map 接口,因此很多特性非常相似。但是,他們有以下不同點:
HashMap 允許鍵和值是 null,而 Hashtable 不允許鍵或者值是 null。
Hashtable 是同步的,而 HashMap 不是。因此,HashMap 更適合于單線程環境,而 Hashtable適合于多線程環境。
HashMap 提供了可供應用迭代的鍵的集合,因此,HashMap 是快速失敗的。另一方面,Hashtable 提供了對鍵的列舉(Enumeration)。
一般認為 Hashtable 是一個遺留的類。
數組(Array)和列表(ArrayList)有什么區別?什么時候應該使用 Array 而不是ArrayList ?
下面列出了 Array 和 ArrayList 的不同點:
Array 可以包含基本類型和對象類型,ArrayList 只能包含對象類型。
Array 大小是固定的,ArrayList 的大小是動態變化的。
ArrayList 提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
對于基本類型數據,集合使用自動裝箱來減少編碼工作量。但是,當處理固定大小的基本數據類型的時候,這種方式相對比較慢。
ArrayList 和 LinkedList 有什么區別?
ArrayList 和 LinkedList 都實現了 List 接口,他們有以下的不同點:
ArrayList 基于索引的數據接口,它的底層是數組。它可以以 O(1)時間復雜度對元素進行隨機訪問。與此對應,LinkedList是以元素列表的形式存儲它的數據,每一個元素都和它的前 一個和后一個元素鏈接在一起,在這種情況下,查找某個元素的時間復雜度是 O(n)。
相對于 ArrayList ,LinkedList 的插入,添加,刪除操作速度更快,因為當元素被添加到集合任 意位置的時候,不需要像數組那樣重新計算大小或者是更新索引。
LinkedList 比 ArrayList 更占內存,因為 LinkedList 為每一個節點存儲了兩個引用,一個指向前一個元素,一個指向下一個元素。也可以參考 ArrayList vs. LinkedList 。
Comparable 和 Comparator 接口是干什么的?列出它們的區別。
參考鏈接: https://www.cnblogs.com/Kevin-mao/p/5912775.html
Java 提供了只包含一個 compareTo()方法的 Comparable 接口。這個方法可以個給兩個對象排序。具體來說,它返回負數,0,正數來表明輸入對象小于,等于,大于已經存在的對象。
Java 提供了包含 compare()和 equals()兩個方法的 Comparator 接口。compare()方法用來給兩個輸入參數排序,返回負數,0,正數表明第一個參數是小于,等于,大于第二個參數。equals()方法需要一個對象作為參數,它用來決定輸入參數是否和 comparator 相等。只有當輸入參數也是一個 comparator 并且輸入參數和當前 comparator 的排序結果是相同的時候,這個方法才返回 true 。
怎樣使Hashmap同步?
HashMap可以通過Map m = Collections.synchronizedMap(hashMap)來達到同步的效果。
什么時候使用Hashtable,什么時候使用HashMap
基本的不同點是Hashtable同步HashMap不是的,所以無論什么時候有多個線程訪問相同實例的可能時,就應該使用Hashtable,反之使用HashMap。非線程安全的數據結構能帶來更好的性能。
如果在將來有一種可能—你需要按順序獲得鍵值對的方案時,HashMap是一個很好的選擇,因為有HashMap的一個子類LinkedHashMap。所以如果你想可預測的按順序迭代(默認按插入的順序),你可以很方便用LinkedHashMap替換HashMap。反觀要是使用的Hashtable就沒那么簡單了。同時如果有多個線程訪問HashMap,Collections.synchronizedMap()可以代替,總的來說HashMap更靈活。
為什么Vector類認為是廢棄的或者是非官方地不推薦使用?或者說為什么我們應該一直使用ArrayList而不是Vector
你應該使用ArrayList而不是Vector是因為默認情況下你是非同步訪問的,Vector同步了每個方法,你幾乎從不要那樣做,通常有想要同步的是整個操作序列。同步單個的操作也不安全(如果你迭代一個Vector,你還是要加鎖,以避免其它線程在同一時刻改變集合).而且效率更慢。當然同樣有鎖的開銷即使你不需要,這是個很糟糕的方法在默認情況下同步訪問。你可以一直使用Collections.sychronizedList來裝飾一個集合。
事實上Vector結合了“可變數組”的集合和同步每個操作的實現。這是另外一個設計上的缺陷。Vector還有些遺留的方法在枚舉和元素獲取的方法,這些方法不同于List接口,如果這些方法在代碼中程序員更趨向于想用它。盡管枚舉速度更快,但是他們不能檢查如果集合在迭代的時候修改了,這樣將導致問題。盡管以上諸多原因,oracle也從沒宣稱過要廢棄Vector.