1 集合和數(shù)組的不同點和相同點
共同點:都是存放數(shù)據(jù)的容器。
不同點:
1.數(shù)組長度不可變,集合長度可變
2.數(shù)組可放基本類型和引用類型;而集合只能放引用類型
3.數(shù)組所有的元素類型必須一致;集合元素類型可變
4.數(shù)組沒有復(fù)寫toString拐辽;集合復(fù)寫了toString(輸出中括號和所有元素)
5.數(shù)組有序可重復(fù);集合(除list外)無序不可重復(fù)擦酌。
2 泛型
面試題
1 java中的泛型是什么俱诸?使用泛型的好處是什么?
答案:
1赊舶、泛型是一種參數(shù)化類型的機制礼搁。它可以使得代碼使用于各種類型罕袋,從而編寫更加通用的代碼赤屋。
2陨仅、泛型是一種編譯時類型確認(rèn)機制。它提供了編譯期的類型安全寓调,確保在泛型類型上只能使用正確類型的對象锌唾,避免了在運行時出現(xiàn)ClassCastException。
2 Java的泛型是如何工作的夺英?什么是類型檫除晌涕?
1、泛型的正常工作是依賴編譯器在編譯源碼的時候痛悯,先進行類型檢查渐排,然后進行類型擦除并且在類型參數(shù)出現(xiàn)的地方插入強制轉(zhuǎn)換的相關(guān)指令實現(xiàn)的。
2灸蟆、編譯器的編譯時擦除了所有類型相關(guān)的信息驯耻,所以在運行時不存在任何類型相關(guān)的信息。例如炒考,List<String>在運行時僅有一個List類型來表示可缚。
3、為什么要進行擦除斋枢?為了避免類型膨脹帘靡。
3 Collection接口
- Collection接口是List接口和Set接口的父接口。
- Iterator接口是對 collection 進行迭代的迭代器瓤帚。
3.1 List接口
- 有序可重復(fù)
-重復(fù):看哈希地址描姚,不看實際地址。(完equals相同戈次,哈希地址也會相同) - 實現(xiàn)類:ArrayList轩勘,LinkedList,Vector怯邪。
ArrayList
底層采用的是數(shù)組來存儲數(shù)據(jù)绊寻,適合查找,效率高;但插入刪除不方便澄步。
LinkedList
底層采用雙向鏈表冰蘑,適合增刪改,方便村缸;查找不方便祠肥。
Vector
數(shù)據(jù)結(jié)構(gòu)與ArrayList相同,采用數(shù)組梯皿。
ArrayList和Vector區(qū)別:
ArrayList線程不安全仇箱,查找效率高;而Vector線程安全索烹,效率低工碾。
3.2 Set接口
- 無序不可重復(fù)弱睦。
- 子接口:SortedSet百姓。
- 實現(xiàn)類:HashSet,LinkedHashSet况木,TreeSet垒拢。
SortedSet接口
底層是一個HashMap,是哈希表火惊。
HashSet類
底層就是哈希表求类。
TreeSet
- 擁有比較的功能。是有序的屹耐。
往TreeSet類中放入的元素必須是實現(xiàn)了Comparable接口類型的數(shù)據(jù)尸疆。實現(xiàn)了Comparable接口的元素會自動調(diào)用compareTo方法。所有這些元素都必須是可互相比較的惶岭。存儲進去的元素可以按照元素的大小自動排序寿弱。如果存放的元素不實現(xiàn)Comparable接口,則TreeSet不會進行排序按灶。
4 Map接口
key和value都是Object症革。key是無序不可重復(fù)的。
Map的存儲結(jié)構(gòu)是哈希表鸯旁。(一維數(shù)組加單向鏈表)
Map的實現(xiàn)類和子接口中key集存儲形式和對應(yīng)Set集合中元素的存儲形式完全相同噪矛。
-
子接口:SortedMap
- 實現(xiàn)類:TreeMap
實現(xiàn)類:HashMap,HashTable
SortedMap接口
- SortedMap中的key等同于SortedSet铺罢。
TreeMap類
- TreeSet類實現(xiàn)了SortedMap接口艇挨。
- key值是有序的。TreeMap的key就是一個TreeSet韭赘。
HashMap類
- key值是無序的雷袋。
- 線程不安全的。性能高。
- 此實現(xiàn)提供所有可選的映射操作楷怒,并允許使用 null 值和 null 鍵蛋勺。
- HashMap有一個子類LinkedHashMap。該類底層用雙向鏈表實現(xiàn)鸠删,可以維護key-value的次序抱完,使得迭代順序和插入順序保持一致。
Hashtable類
- 線程安全的刃泡。性能低巧娱。
- key和value都不允許為null。如果試圖把null放進Hashtable中烘贴,將會引發(fā)NullPointerException異常禁添。
- 除了這兩點不同,與HashMap沒什么不同桨踪。
與Vector類似老翘,盡量少用Hashtable實現(xiàn)類,即使需要創(chuàng)建線程安全的Map實現(xiàn)類锻离,也可以通過Collections工具類把HashMap變成線程安全的铺峭,無需使用Hashtable實現(xiàn)類。
HashMap和Hashtable區(qū)別:
1 線程是否安全
2 key和value是否允許為null汽纠。
面試題
1 HashMap中的put方法和get方法在內(nèi)存中是如何實現(xiàn)的卫键?
put方法:
首先放入第一個元素,元素的key調(diào)用hashCode方法得到哈希值虱朵,這個值就是一維數(shù)組的下標(biāo)莉炉,就是桶的位置。向桶的單向鏈表中插入該元素碴犬。
放入第二個元素絮宁,key調(diào)用hashCode方法得到哈希值,發(fā)現(xiàn)與第一個元素的哈希值是一樣的翅敌,說明在同一個桶中羞福,之后調(diào)用equals方法,比較第一個元素的key值和第二個元素的key值蚯涮,看是否相同治专。如果是true,則第二個元素覆蓋第一個元素而存在遭顶,鍵值對entry會發(fā)生變化张峰;如果返回false,則把第二個元素插入到鏈表頭(即把最新的元素放到鏈表頭)棒旗,舊的數(shù)據(jù)會被最新的元素的next變量引用著喘批。
get方法:
通過key調(diào)用hashCode方法撩荣,算出元素在數(shù)組中的下標(biāo)(即找到桶的位置),之后key通過調(diào)用equals方法找與尋找key相同的對應(yīng)的節(jié)點饶深。
2餐曹、Java中ArrayList和LinkedList區(qū)別。
- ArrayList底層是基于數(shù)組實現(xiàn)的敌厘,而LinkedList底層基于循環(huán)雙向鏈表實現(xiàn)的台猴。
- 對于隨機訪問get和set,ArrayList優(yōu)于LinkedList俱两,因為LinkedList要移動指針饱狂。
- 對于新增和刪除操作add和remove,LinkedList比較占優(yōu)勢宪彩,因為ArrayList要移動數(shù)據(jù)休讳。
3 set為什么能夠保證唯一性,了解集合怎么去重尿孔?
俊柔??纳猫?婆咸?竹捉?
底層實現(xiàn)了HashMap
對于HashSet中保存的對象芜辕,主要要正確重寫equals方法和hashCode方法,以保證放入Set對象的唯一性
雖說是Set是對于重復(fù)的元素不放入块差,倒不如直接說是底層的Map直接把原值替代了(這個Set的put方法的返回值真有意思)
HashSet沒有提供get()方法侵续,愿意是同HashMap一樣,Set內(nèi)部是無序的憨闰,只能通過迭代的方式獲得
4 HashMap與Hashtable的區(qū)別與聯(lián)系状蜗。
區(qū)別:1、線程是否安全與效率高低:HashMap
是線程不安全的鹉动,效率高轧坎;而Hashtable是線程安全的,效率低泽示。
2缸血、是否允許為null:HashMap允許key和value為null,而Hashtable不允許械筛。
5 Hashtable和ConCurrentHashMap的區(qū)別捎泻。
答案1:
參考:https://www.cnblogs.com/sikewang/p/5542026.html
Hashtable是synchronized,但是ConcurrentHashMap的同步性能更好埋哟,因為它僅僅根據(jù)同步級別對map的一部分進行上鎖笆豁。
ConCurrentHashMap提供更強的線程安全性。
答案2:
參考:https://www.cnblogs.com/supertang/p/4149786.html
ConcurrentHashMap和Hashtable主要區(qū)別就是圍繞著鎖的粒度以及如何鎖。
1闯狱、Hashtable的實現(xiàn)方式--鎖整個hash表煞赢。
2、ConcurrentHashMap的實現(xiàn)方式--鎖桶哄孤。而且 只有寫線程才需要鎖定耕驰,而讀線程幾乎不受限制,大大提升并發(fā)性录豺。
6 Java集合類框架的基本接口有哪些朦肘?
Collection:代表一組對象,每個對象都是它的子元素双饥。
Set:不包括重復(fù)元素的Collection媒抠。
List:有序可重復(fù)的Collection。
Map:鍵值對咏花。
7 Java中的HashMap的工作原理是什么趴生?
1、HashMap基于哈希原理昏翰,通過put和get發(fā)存儲和獲取對象苍匆。當(dāng)將鍵值對傳遞給put方法時,它調(diào)用鍵對象的hashCode方法來計算hashcode棚菊,然后找到bucket位置來存儲值對象浸踩。
2、當(dāng)獲取對象時统求,通過鍵對象的equals方法找到正確的鍵值對检碗,然后返回值對象。
3码邻、HashMap使用LinkedList來解決碰撞問題折剃,當(dāng)發(fā)生碰撞了,對象將會存儲在下一個節(jié)點中像屋。HashMap在每個LinkedList節(jié)點中存儲鍵值對對象怕犁。
4、當(dāng)兩個不同的鍵對象的hashcode相同時會發(fā)生什么己莺?他們會存儲在同一個bucket位置的LinkedList中奏甫。可以通過鍵對象的equals方法用來找到鍵值對篇恒。
HashMap的工作原理扶檐?
HashMap是基于hashing的原理,我們使用put(key, value)存儲對象到HashMap中胁艰,使用get(key)從HashMap中獲取對象款筑。當(dāng)我們給put()方法傳遞鍵和值時智蝠,我們先對鍵調(diào)用 hashCode()方法,返回的hashCode用于找到bucket位置來儲存Entry對象奈梳。
“當(dāng)兩個對象的hashcode相同會發(fā)生什么杈湾?”
因為hashcode相同,所以它們的bucket位置相同攘须,‘碰撞’會發(fā)生漆撞。因為HashMap使用LinkedList存儲對象,這個 Entry(包含有鍵值對的Map.Entry對象)會存儲在LinkedList中于宙。
“如果兩個鍵的hashcode相同浮驳,你如何獲取值對象?”
當(dāng)我們調(diào)用get()方法捞魁,HashMap會使用鍵對象的hashcode找到bucket位置至会,找到bucket位置之后,會調(diào)用key.equals()方法去找到鏈表中正確的節(jié)點谱俭,最終找到要找的值對象奉件。
“如果HashMap的大小超過了負(fù)載因子(load factor)定義的容量,怎么辦昆著?”
capacity:桶的數(shù)量
size:鏈表元素的個數(shù)大小
負(fù)載因子=size/capacity
默認(rèn)負(fù)載因子為0.75
默認(rèn)初始化容量:16
負(fù)載因子越大县貌,碰撞多。
默認(rèn)的負(fù)載因子大小為0.75凑懂,也就是說煤痕,當(dāng)一個map填滿了75%的bucket時 候,和其它集合類(如ArrayList等)一樣征候,將會創(chuàng)建原來HashMap大小的兩倍的bucket數(shù)組杭攻,來重新調(diào)整map的大小祟敛,并將原來的對象放 入新的bucket數(shù)組中疤坝。