1)ArrayList 和 Vector 的區別。
答:
ArrayList
1、實現原理:采用動態對象數組實現,默認構造方法創建了一個空數組
2、第一次添加元素,擴展容量為10,之后的擴充算法:原來數組大小+原來數組的一半
3、當插入、刪除位置比較靠前時,與鏈表比較,不適合進行刪除或插入操作
4、為了防止數組動態擴充次數過多,建議創建ArrayList時,給定初始容量
5、多線程中使用不安全,適合在單線程訪問時使用,效率較高
Vector
1、實現原理:采用動態數組對象實現,默認構造方法創建了一個大小為10的對象數組
2、擴充的算法:當增量為0時,擴充為原來的2倍,當增量大於0時,擴充為原來大小+增量
3、當插入、刪除位置比較靠前時,與鏈表比較,不適合刪除或插入操作
4、為了防止數組動態擴充次數過多,建議創建Vector時,給定初始容量
5、線程安全,適合在多線程訪問時使用,效率較低
集合的使用注意:
若使用集合來存儲多個不同類型的元素(對象),那么在處理時會比較麻煩
在實際開發中不建議這樣使用,我們應該在一個集合中存儲相同的類型對象
(2)說說 ArrayList,Vector, LinkedList 的存儲性能和特性。
1、ArrayList采用的是數組形式來保存對象的,這種方式將對象放在連續的位置中,所以最大的缺點就是插入刪除時非常麻煩
2、LinkedList采用的將對象存放在獨立的空間中,而且在每個空間中保存下一個鏈接的索引,但是缺點就是查找非常麻煩,要從第一個索引開始
3、ArrayList和Vector都是用數組方式存儲數據,此數組元素數要大於實際的存儲空間以便進行元素增加和插入操作,他們都允許直接用序號索引元素,但是插入數據元素涉及到元素移動等內存操作,所以索引數據快而插入數據慢
4、Vector使用了synchronized方法(線程安全),所以在性能上比ArrayList要差些
5、LinkedList使用雙向鏈方式存儲數據,按序號索引數據需要向前或向后遍歷數據,索引索引數據慢,插入數據時只需要記錄前后項即可,所以插入的速度快
(3)快速失敗 (fail-fast) 和安全失敗 (fail-safe) 的區別是什么?
1、快速失敗(fail-fast)
在用迭代器遍歷一個集合對象時,如果遍歷過程中對集合對象的內容進行修改(增加、刪除、修改),則會拋出Concurrent Modification Exception.
原理:迭代器在遍歷時直接訪問集合中的內容,並且在遍歷過程中使用一個modCount變量。集合在被遍歷期間如果內容發生變化,就會改變modCount的值。每當迭代器使用hashNext()/next()遍歷下一個元素之前,都會檢測modCount變量是否為expectedmodCount值,是的話就返回遍歷;否則拋出異常,終止遍歷。
注意:這里異常的拋出條件是檢測到modCount!=expectedmodCount這個條件。如果集合發生變化時修改modCount值剛好又設置為了expectedmodCount值,則異常不會拋出。因此,不能依賴於這個異常是否拋出而進行並發操作的編程,這個異常只建議用於檢測並發修改的bug。
場景:java.util包下的集合類都是快速失敗的,不能在多線程下發生並發修改(迭代過程中被修改)。
2、安全失敗(fail-safe)
采用安全失敗機制的集合容器,在遍歷時不是直接在集合內容上訪問的,而是先復制原有集合內容,在拷貝的集合上進行遍歷。
原理:由於迭代時是對原集合的拷貝進行遍歷,所以在遍歷過程中對原集合所作的修改並不能被迭代器檢測到,所以不會觸發Concurrent Modification Exception。
缺點:基於拷貝內容的優點是避免了Concurrent Modification Exception,但同樣地,迭代器並不能訪問到修改后的內容,即:迭代器遍歷的是開始遍歷那一刻拿到的集合拷貝,在遍歷期間原集合發生的修改迭代器是不知道的
場景:java.util.concurrent包下的容器都是安全失敗,可以在多線程下並發使用,並發修改。
(4)hashmap 的數據結構。
數組+鏈表(Java7之前包括Java7)
數組+鏈表+紅黑樹(從Java8開始)
這里的紅黑樹與鏈表都是鏈式結構
HashMap內部維護了一個數組,數組中存放鏈表的鏈首或紅黑樹的樹根
當鏈表長度超過8時,鏈表就轉換為紅黑樹,利用紅黑樹快速增刪改查的特點提高HashMap的性能,在紅黑樹節點數量小於6時,紅黑樹轉變為鏈表。
(5)HashMap 的工作原理是什么?
HashMap基於hashing原理,我們通過put()和get()方法存儲和獲取對象。當我們將鍵值對傳遞給put()方法時,它調用鍵對象的hashCode()方法來計算hashcode,然后找到bucket位置來存儲值對象。當獲取對象時,通過鍵對象的equals()方法找到正確的鍵值對,然后返回值對象。HashMap使用鏈表來解決碰撞問題,當發生碰撞了,對象將會存儲在鏈表的第一個節點,鏈接原先的對象節點,HashMap在每個鏈表節點中存儲鍵值對對象。