1. 程式人生 > 遊戲資訊 >峽谷晚報:管澤元看好T1奪冠、Rookie蘇小洛為上海捐款

峽谷晚報:管澤元看好T1奪冠、Rookie蘇小洛為上海捐款

Arraylist 與 LinkedList 區別?

  • 是否保證執行緒安全: ArrayList 和 LinkedList 都是不同步的,也就是不保證執行緒安全;
  • null儲存
  • 底層資料結構: Arraylist 底層使用的是 Object 陣列;LinkedList 底層使用的是 雙向連結串列 資料結構
  • 插入和刪除是否受元素位置的影響:
    • ArrayList 採用陣列儲存,所以插入和刪除元素的時間複雜度受元素位置的影響。 比如:執行add(E e)方法的時候, ArrayList 會預設在將指定的元素追加到此列表的末尾,這種情況時間複雜度就是 O(1)。但是如果要在指定位置 i 插入和刪除元素的話時間複雜度就為 O(n-i)。因為在進行上述操作的時候集合中第 i 和第 i 個元素之後的(n-i)個元素都要執行向後位/向前移一位的操作。
    • LinkedList 採用連結串列儲存,所以,如果是在頭尾插入或者刪除元素不受元素位置的影響(add(E e)、addFirst(E e)、addLast(E e)、removeFirst() 、 removeLast()),近似 O(1),如果是要在指定位置 i 插入和刪除元素的話(add(int index, E element),remove(Object o)) 時間複雜度近似為 O(n) ,因為需要先移動到指定位置再插入。
    • 是否支援快速隨機訪問: LinkedList 不支援,而 ArrayList 支援。記憶體空間佔用: ArrayList 的空 間浪費主 list 列表的結尾會預留一定的容量空間,而 LinkedList 的空間花費每一個元素都要存放直接後繼和直接前驅以及資料

    以我自己的經驗,當然我也測試過,如果只是要實現一個列表的功能,也就是加強版陣列吧,使用ArrayList是效率比較高的,因為佔用空間小、支援隨機訪問,當然我們想象中連結串列在增刪元素方面有優勢,因為只需要增刪指標而不用像Array一樣挨個往後挪,但是連結串列不支援隨機訪問,增刪前得先挨個挨個往後找到位置,尤其是在表一半往後的地方,LinkedList效率是很差的。當然如果要實現佇列或者棧,雙向連結串列還是非常有優勢的。

    Arrays.asList既不是ArrayList也不是LinkedList,而僅僅是把陣列進行了包裝,不能新增不能刪除,本質還是一個數組。可以使用ArrayList(Arrays.asList(T[] a)

     

    ArrayDeque 與 LinkedList 的區別

    ArrayDeque 和 LinkedList 都實現了 Deque 介面,兩者都具有佇列的功能

    ArrayDeque 是基於陣列和雙指標來實現,而 LinkedList 則通過連結串列來實現。

    • ArrayDeque 不支援儲存 NULL,但 LinkedList 支援。
    • ArrayDeque 插入時可能存在擴容過程, 不過均攤後的插入操作依然為 O(1)。雖然 LinkedList 不需要擴容,但是每次插入資料時均需要申請新的堆空間,均攤效能相比更慢。

    從效能的角度上,選用 ArrayDeque 來實現佇列要比 LinkedList 更好。此外,ArrayDeque 也可以用於實現棧。

    ArrayDeque的增刪都是通過移動頭尾指標實現的,若陣列容量不夠,則進行double擴容。容量總是為2的冪次。在頭尾指標移動的時候,使用取餘(陣列長度-1再相與)的方式在陣列上迴圈移動。

    Map和Set:Set基於Map實現。

    • HashMap: JDK1.8 之前 HashMap 由陣列+連結串列組成的,陣列是 HashMap 的主體,連結串列則是主要為了解決雜湊衝突而存在的(“拉鍊法”解決衝突)。JDK1.8 以後在解決雜湊衝突時有了較大的變化,當連結串列長度大於閾值(預設為 8)且陣列長度大於64(如果小於 64,那麼先進行陣列擴容,而不是轉換為紅黑樹)時,將連結串列轉化為紅黑樹,以減少搜尋時間。執行緒不安全,ConcurrentHashMap
    • LinkedHashMap: LinkedHashMap 繼承自 HashMap,所以它的底層仍然是基於拉鍊式雜湊結構即由陣列和連結串列或紅黑樹組成。另外,LinkedHashMap 在上面結構的基礎上,增加了一條雙向連結串列,使得上面的結構可以保持鍵值對的插入順序。同時通過對連結串列進行相應的操作,實現了訪問順序相關邏輯。
    • HashTable:和 HashMap 類似,效率更低,但它是執行緒安全的。已淘汰,使用 ConcurrentHashMap 來支援執行緒安全,效率會更高,因為引入了分段鎖。無紅黑樹
    • TreeMap:基於紅黑樹,元素有序,可自定義排序,訪問時間為o(logn)
    • TreeSet: 基於TreeMap實現,可自定義排序。
    • LinkedHashSet:內部是通過 LinkedHashMap 來實現的,唯一性,元素的增刪滿足FIFO

     

    HashMap 和 Hashtable 的區別

    • 執行緒是否安全: HashMap 是非執行緒安全的,Hashtable 是執行緒安全的,因為 Hashtable 內部的方法基本都經過synchronized 修飾。(如果你要保證執行緒安全的話就使用 ConcurrentHashMap 吧!
    • 效率: 因為執行緒安全的問題,HashMap 要比 Hashtable 效率高一點。
    • 對 Null key 和 Null value 的支援: HashMap 可以儲存 null 的 key 和 value,但 null 作為鍵只能有一個,null 作為值可以有多個;Hashtable 不允許有 null 鍵和 null 值,否則會丟擲 NullPointerException。
    • 初始容量大小和每次擴充容量大小的不同 : ① 建立時如果不指定容量初始值,Hashtable 預設的初始大小為 11,之後每次擴充,容量變為原來的 2n+1。HashMap 預設的初始化大小為 16。之後每次擴充,容量變為原來的 2 倍。② 建立時如果給定了容量初始值,那麼 Hashtable 會直接使用給定值,而 HashMap 會將其擴充為 2 的冪次方大小。也就是說 HashMap 總是使用 2 的冪作為雜湊表的大小
    • 底層資料結構: 紅黑樹,table沒有

     

    HashMap 的長度為什麼是 2 的冪次方

    實際上在雜湊表中我們使用的並不是直接的雜湊值,因為自帶的雜湊值是分佈於-2^31, 2^31-1的區間的,因此使用雜湊值對陣列長度進行取餘,這樣雜湊值就能分佈在陣列長度內,而如果陣列的長度是2的冪次方的話,取餘運算就等價於長度減1在相與的運算,大大提升計算雜湊值的速度。

     

    HashMap 和 TreeMap 區別

    TreeMap 和HashMap 都是Map的實現方式 ,但TreeMap還實現了NavigableMap介面和SortedMap 介面,可以對元素進行搜尋和排序。

    底層實現方式不同

     

    HashSet 如何檢查重複

    首先計算hashcode 若hashcode存在相同 則呼叫equal,因為hashcode相同僅僅是equal的必要不充分條件。

     

    HashSet在底層為什麼要把value設為一個Object?而不存null

    因為HashSet的add和remove方法底層是HashMap的方法,HashMap的put方法若已有這個key會返回這個value,若沒有該key會返回null,而HashSet的add方法在包裝put方法時,會返回put方法返回值是否為null,如果HashSet存得value是null,那麼無論底層map中是否已經有了這個key,put方法都會返回null,add方法也就都會返回true,也就無法判斷是否新增成功了。

     

    HashMap的底層實現(HashMap並不是直接用元素的hashcode

    是通過連結串列陣列的方式去實現的,元素首先通過Key值進行雜湊值的計算,然後將雜湊值通過雜湊map的hash函式也就是擾動函式處理之後能夠減少雜湊衝突,如果hash相同,就比較2個元素的Key值,如果相同那麼就直接覆蓋,如果不同就將該元素加入到下掛連結串列中,當然現在hashmap現在的連結串列如果長度大於預設閾值8時且當前陣列長度小於64,否則會進行陣列擴容,將會被轉化為紅黑樹進行效率更高的存取。

     

    ConcurrentHashMap

    不同於直接用sync將HashMap上鎖的HashTable,Concurrent採用了分段鎖。也就是將資料分段,在寫資料時,一個執行緒只會鎖定具體要寫的一段資料,而其他執行緒想要獲取這個物件則不會被阻塞,可以同時操作對該物件的其他段。讀取資料不加鎖。

    Concurrent在內部採用了Segment連結串列陣列的結構,一個Segment中存放若干HashEntry,類似於一個HashMap,是一個連結串列陣列,所以在訪問元素時,首先要經過一次Hash,定位到Segment,第二次Hash才定位到Value。

    JDK1.8後 因為synchronized優化,Concurrent底層使用node陣列類似hashmap,使用Synchronized+CAS來實現執行緒安全,只鎖頭結點,相當於上鎖粒度更細。而且1.8後,Concurrent也在連結串列過長時轉為紅黑樹。

     

    List.toArray(T[] a): size表示將List複製到a中,如果大小足夠,就會把list內容裝進該陣列,並在末尾新增一個null,說明list元素已經新增完了;若不夠,將另外建立一個足夠大小的陣列,並且將其返回給接收的陣列。而且不支援基本資料型別,只能使用引用資料型別。