美團外賣配送部後臺開發面經---牛客網

一、hashMap和ConcurrentHashMap的區別數組

     答:hashMap是無序鍵不可重複值能夠重複;線程不安全的;可存一個null鍵和多個null值,「數組加鏈表」結構,數組長度默認16;經過key的hashCode值去決定該鍵值對存      在數組哪一個空間上即hashCode%lenth=index,此處length通常默認16,若是該位置上已經有其餘的;若要使其線程安全,則可以使用Collections類的方法:Map<String,String> map = Collections.synchronizedMap(new HashMap());安全

        ConcurrentHashMap:是在hashMap的基礎上,把數據分紅許多的segment(默認16個)每次操做時會對該segment(一個存放Entry的桶,默認實現ReentrantLock)加鎖,避免多線程鎖的概率,提升併發效率多線程

  補充:併發

    問題¥:hashMap中key爲null的值存在哪裏?高併發

            for循環會默認在table[0]中查找key爲null的值,如果找到了,就把這個新value值賦給這個元素的value,並返回原來的那個value,若沒找到,就把該鍵值對存到table[0]鏈表的表頭。spa

          

 

 

   問題¥¥:ConcurrentHashMap詳解:線程

        ConcurrentHashMap是線程安全的(基於lock實現的,同步的時候鎖住的不是整個對象,而加了synchronized的是鎖住了整個的對象),實現了Map接口,他是在hashMap的基礎上,將數指針

      據分爲不少個小的segment(桶,他繼承了ReentrantLock),默認16,每次操做都對segment加鎖,避免多線程的概率,提升併發效率,從他的源碼中能夠看出,他引入了一個「分段鎖」的概code

      念,就是能夠看做把一個Map分紅不少個HashTable(hashTable每次是對一整張表加鎖),根據key.hashCode()來決定把key放到哪一個hashTable中,get時根據計算出來的key.hashCode(),從哪對象

      個hashTable中拿出

      裝載因子:0.75,若是表中75%的位置已經填入元素,就會擴容兩倍(例如:默認初始容量爲16,當已用空間爲12(75%)時,會自動擴容爲2*16=32)

      裝載因子就是hash表中已佔空間和所有空間的比值,默認0.75

        初始容量默認爲16

      裝載因子越大,空間利用率越高,可是衝突機會加大,增大查詢數據的開銷,查詢速度慢,反而空間利用率低,衝突機會減少

二、hashMap內部具體如何實現的

          hashMap實現了map接口,無序不重複,可存一個null鍵和多個null值,線程不安全,,底層是「數組加鏈表「結構,默認初始容量是16,加載因子是0.75,當調用put方法存儲鍵值對時,會先調用key的 

      hashCode方法計算hashCode值,經過hashCode%length=index來決定把Entry存在數組的下標,此時如果該下標已經存在entry了,則調用key的equals方法,再去比較,若此時不相同則把新添加進來的entry

   存在鏈表頭部,以前的entry日後移,此時如果用equals比較相同表示重複則用新的value去替換舊的value

三、若是hashMap的key是一個自定義的類,怎麼辦

       重寫equals方法和hashCode方法,若是不用對象的話就用的是那些已經默認重寫過equals和hashCode的String或者其餘的一些引用對象,如Date,因此若是是本身定義的類時就要重寫equals和hashCode方法,由於hashCode方法構造的hashCode值是默認的內存地址,這樣即使有相同含義的兩個對象,比較也是不相等的,例如:

          User u1 = new User (「hello」,」ren」);

          User u2 = new User (「hello」,」ren」);

  正常理解這兩個對象加入HashMap應該是同樣的,只添加一個,添加的第二個的value把第一個的覆蓋掉,可是若是不重寫的話比較是其地址,不相等,添加的是兩個。

  補充:

        問題¥:equals和==的區別:

       1)對於==:用於基本數據類型比較的是數值大小是否相等,對於非基本數據類型(引用類型)比較其地址是否一致

    2)對於equals:不能用於比較基本數據類型,只能用於比較引用類型,沒有重寫equals方法時,直接比較的是兩個對象的地址,如果重寫了equals方法,如

  String、Date等比較的是所指向對象的內容

四、爲何重寫equals還要重寫hashcode?

  hashCode沒有重寫時用地址構造hashCode值,地址不一樣值不一樣,此時如果有兩個對象,u.equals(u1)只能說明內容相同(此時已經重寫了equals方法),調用map.put()方法,hashCode值不一樣,就會把u和u1分別放入兩個桶中,可是這時候把map中的內容打印出來就會發現:

    1、這時候就會形成重複

       

 

        2、再者hashCode就是肯定entry存在哪一個桶中的,此時如果只知道兩個兩個鍵equals方法爲true,可是不知道是否在一個桶,這樣的比較毫無心義

       

 

     通俗來說:想一想,你要在一個桶裏找東西,你必須先要找到這個桶啊,你不經過重寫hashcode()來找到桶,光重寫equals()有什麼用啊

  重寫後的hashCode方法中經過String類型參數去調用了String類的hashCode方法,此時如果參數相同則值相同,參數不一樣值不一樣,如若此處name,title參數是其餘引用類型,則在其餘類型中也要重寫hashCode和equals方法

  

五、ArrayList和LinkedList的區別,若是一直在list的尾部添加元素,用哪一個效率高?

  (1)ArrayList:底層是數組實現,有下標空間連續因此查詢快,隨機讀取效率很高,增刪慢,存儲的是對象的引用而不是對象自己,可是線程不安全,替代了vector

      LinkedList:底層是基於鏈表實現的,有指針因此增刪快(好比新來一個節點只須要把上一個節點告訴他(上個節點的指針有指向)便可),但空間不連續查詢很慢,須要遍歷整個鏈表,不具備隨機訪問性

    (2)效率:

      list開始LinkedList>ArrayList

      list中間LinkedList=ArrayList

      list最後LinkedList<ArrayList

      list隨機插入LinkedList>ArrayList

相關文章
相關標籤/搜索