各種集合比較

HashMap為什么允許為null?
首先put的時(shí)候,就會(huì)對(duì)key==null做一個(gè)判斷,對(duì)于key==null的Entry,會(huì)調(diào)用putForNullKey直接去遍歷table[0]上的哈希桶,尋找e.key=null的Entry或者沒有找到遍歷結(jié)束。找到則覆蓋原值,沒找到就調(diào)用addEntry方法添加一個(gè)key為null的Entry。

為什么說HashMap是無序的?(因?yàn)槠涑跏蓟臅r(shí)候采用的是位哈希算法)
HashMap在第一次put的時(shí)候完成初始化,通過模運(yùn)算(其實(shí)是高或低16位的按位與運(yùn)算的位哈希算法 使1均勻分布,有利于泊松分布,降低哈希碰撞的概率)來計(jì)算哈希槽中的落槽位置即數(shù)組下標(biāo)的(由于我們無法預(yù)料按位與的結(jié)果,所以這里是無序的)。

HashMap高并發(fā)情況下的問題?改善?
HashMap高并發(fā)情況下的擴(kuò)容數(shù)據(jù)丟失以及死鏈問題。因?yàn)閔ashmap線程不安全,所以如果兩個(gè)線程同時(shí)對(duì)同一Entry進(jìn)行操作,會(huì)丟失數(shù)據(jù)。死鏈問題:Entry的next被并發(fā)修改導(dǎo)致的對(duì)象丟失,兩個(gè)對(duì)象互鏈,對(duì)象自己互鏈的中兩個(gè)對(duì)象互鏈產(chǎn)生的死鎖。改善,1.8Hashmap采用對(duì)原先鏈表的引用,保證有序性,除此之外,可以使用ConcurrentHashmap。1.7使用segement分段鎖,1.8使用CAS保證有序,voliate關(guān)鍵字保證可見。

HashMap存放自定義類的時(shí)候,為什么要重寫hashCode和equals。
因?yàn)槲覀円ㄟ^hashCode然后模運(yùn)算(現(xiàn)在是按位與的哈希算法)來計(jì)算table中的下標(biāo),然后遍歷這之后的鏈表,通過equals比較有沒有相同的key,如果有直接覆蓋value,因?yàn)橐ㄟ^equals比較有沒有相同的key,所以要重寫equals,而由于約定并且提高散列表性能,重寫equals必須重寫hashCode。

HashMap與Hashtable比較。


image.png

上面確認(rèn)在數(shù)組中的索引不同即哈希值的使用不同,hashtable直接使用對(duì)象的哈希值求出索引,hashmap則進(jìn)行取模運(yùn)算(按位與),再次哈希。

HashMap要想實(shí)現(xiàn)線程安全,需要調(diào)用Collections類的靜態(tài)方法synchronizeMap()實(shí)現(xiàn)

HashMap中的key可以為任意對(duì)象或者數(shù)據(jù)類型嗎?
可以為null,但不能是可變對(duì)象,如果是可變對(duì)象的話,對(duì)象中的屬性改變,則對(duì)象的HashCode也改變,導(dǎo)致下次無法查找到table下標(biāo),引起數(shù)據(jù)丟失。

HashMap與ConcurrentHashMap的區(qū)別?
以下是1.7的區(qū)別:
HashMap線程不安全,ConcurrentHashMap線程安全。
HashMap是fail-fast的,ConcurrentHashMap是fail-safe的。
ConcurrentHashMap在1.8以前,使用了Segment分段鎖。

HashTable與ConcurrentHashMap的區(qū)別?
hashTable是使用了一把鎖鎖住了整個(gè)對(duì)象。效率非常低下,當(dāng)一個(gè)線程訪問同步方法的時(shí)候,其它線程訪問同步方法,可能會(huì)進(jìn)入阻塞或者輪詢的狀態(tài)。
ConcurrentHashMap則是使用分段鎖,當(dāng)一個(gè)線程占用鎖訪問其中一個(gè)數(shù)據(jù)的時(shí)候,其它段的數(shù)據(jù)也能被其它線程訪問。

LinkedHashMap與HashMap的區(qū)別?

  1. LinkedHashMap是HashMap的子類。
  2. 底層是都是散列表,不過HashMap是數(shù)組+鏈表。LinkedHashMap是數(shù)組+雙向鏈表。
  3. put方法幾乎完全相同,只不過進(jìn)行了一些細(xì)節(jié)上的調(diào)整。
  4. 擴(kuò)容操作的調(diào)整,基于性能和LinkedHashMap自身的考量,重哈希過程(transfer方法)進(jìn)行了重寫。

HashMap與HashSet區(qū)別?

  1. HashMap實(shí)現(xiàn)了Map接口,HashSet實(shí)現(xiàn)了Set接口
  2. Map存儲(chǔ)K-V,HashSet存儲(chǔ)對(duì)象(把對(duì)象作為key存儲(chǔ),僅僅存儲(chǔ)key)
  3. 調(diào)用put()向map中添加元素,調(diào)用add()向set中添加元素
  4. HashMap使用key的HashCode來進(jìn)行再哈希。HashSet使用成員對(duì)象來計(jì)算HashCode值,對(duì)于兩個(gè)對(duì)象hashCode可能相同,所以使用equals來判斷對(duì)象向鄧姓。
  5. HashMap比HashSet要快,因?yàn)镠ashMap使用唯一個(gè)key獲取對(duì)象。
  6. HashSet是對(duì)HashMap的封裝。

HashSet如果保證集合沒有重復(fù)元素?
HashSet底層是對(duì)HashMap的封裝,將對(duì)象作為HashMap的key,一個(gè)通用的Object設(shè)置位value,因而當(dāng)對(duì)象重復(fù)(即對(duì)象的equals和hashCode都相同時(shí)),我們會(huì)將value覆蓋,而key不會(huì)有任何的改變。這也是為什么Set方法存的對(duì)象必須重寫Object的equals和hashCode的原因。因?yàn)镺bject是所有類的超類。

ArrayList和Vector區(qū)別?
同:都是List接口實(shí)現(xiàn)子類,并且存儲(chǔ)有序(List接口都有序),底層是數(shù)組??梢园凑瘴恢萌〕鲈?,允許重復(fù)和null。

異:同步性:ArrayList不同步,線程不安全,Vector同步,線程安全,但我們棄用,可以使用Collections工具類來構(gòu)建出同步的ArrayList而不用Vector。
擴(kuò)容:ArrayList使用位運(yùn)算符(JDK1.5) 擴(kuò)容成1.5倍,Vector則擴(kuò)容成兩倍。

List和Map的不同?
存儲(chǔ)結(jié)構(gòu):List存儲(chǔ)單列集合,Map存儲(chǔ)K-V
元素重復(fù):List元素可以重復(fù),Map中key不能重復(fù)
是否有序:List有序,Map無序。

HashSet使用什么方法判斷重復(fù)元素?
equals和hashCode。HashSet封裝了HashMap
集合使用put方法完成Entry的放置,hashCode可以用來計(jì)算落槽位置,equals方法可以用來判斷key是否相等,所以要重寫這兩個(gè)方法。

ArrayList和LinedList的存儲(chǔ)特性?
ArrayList底層是數(shù)組,因?yàn)樵L問速度快。
LinedList底層是雙向鏈表,增刪速度快。

Collection(所有類集接口的父接口)

  • List
  1. ArrayList
  2. LinkedList
  3. Vector(了解,已過時(shí))
  • Set
  1. HashSet
  2. LinkedHashSet
  3. TreeSet
  • Map
  1. HashMap
  2. LinkedHashMap
  3. TreeMap
  4. ConcurrentHashMap
  5. Hashtable(了解,,已過時(shí))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容