1. 程式人生 > >Java集合相關面試題整理

Java集合相關面試題整理

1、為什麼要使用集合?

        針對於陣列的缺點出現的:陣列的長度固定的,且只能存放一種型別的資料;

2、集合的特點?

        (1)長度可擴充套件,可以存放多種型別的資料;

        (2)只能存放引用型別的資料,哪怕存放基本型別進去,也會先將其轉換為包裝型別才儲存進去;

        (3)集合存放的只是物件的引用,物件本身還是儲存在堆中的;

        (4)有倆個基本的介面,iterator介面(collection是list與set的父介面)與map;

           ps:繼承順序list、set ----> collection ----> iterable(其中分裝了iterator介面)

3、List集合相關問題:

        (1)List介面的典型實現:

                      1>、ArratList:底層是陣列,隨機獲取元素快,刪除、新增慢,執行緒不安全;

                      2>、vector:底層為陣列,隨機獲取元素快,刪除,新增慢,執行緒安全;

                      3>、LinkedList:底層為連結串列結構,隨機獲取元素慢,新增、刪除元素較快,執行緒不安全的;

        (2)ArrayList與LinkedList的區別?(此處只講隨機獲取元素以及新增刪除方面的異同)

                      ArrayList採用的是陣列的方式實現List介面的,陣列是採用一段連續的儲存單元來儲存資料,它的優點是若通過索引的方式快速獲定位物件的位置,但是若是新增/刪除資料速度會比較慢,因為需要移動所有元素的儲存的位置;

                      LinkedList採用的是連結串列的方式實現List介面的,對於線性連結串列來說,新增或者刪除資料只需要處理節點間的引用就行(線性連結串列講解:https://mp.csdn.net/mdeditor/83628312#),但是對於隨機得到元素來說速度很慢,因為採用的是連結串列,故先要遍歷連結串列;

       (3)ArrayList與Vector的區別?

                     1>、ArrayList是執行緒非安全的,Vector是執行緒安全的;

                     2>、ArrayList的中的元素如果超過其容量的話,其容量會擴容50%+1,但是Vector卻會翻倍;

      (4)陣列與連結串列異同?

                   相同點: 陣列是線性的,連結串列也是線性的;陣列的訪問是通過索引來訪問的,連結串列型資料的訪問是通過移動指標,且只能從頭到尾;

                    不同點:陣列元素在記憶體中是連續的,在棧區,而連結串列元素在記憶體中是不連續的,在堆區;

4、Set集合的相關問題:

       (1)Set介面的典型實現

                    1>、hashSet:底層採用hash演算法,不保證元素的新增順序,查詢效率高(原因見:);

                    2>、LinkedHashSet:hashSet的子類,在hashSet的基礎上實現了連結串列結構,及保證了元素的新增順序,整體效能低於hashSet(隨機訪問元素效率慢);

                    3>、TreeSet:不能儲存null,底層實現了紅黑樹演算法,有序,擅長於範圍查詢;

      (2)hashSet與hashMap的關係?

                    1>、hashSet相當於(key,null)的hashMap;

      (3)hashSet、LinkedHashSet的區別與TreeSet的區別?

                    hashSet與LinkedHashSet的區別僅在後者的底層實現了線性連結串列(按照插入的順序排序);

                    hashSet與TreeSet的區別:

                            1>、hashSet的key可以為null,但是TreeSet不行;

                            2>、hashSet不能保證插入的元素的順序,treeSet是有序的(自己的演算法排序);

                            3>、hash底層實現的是hash表演算法,而TreeSet實現的是紅黑樹演算法;

                            4>、hashSet是通過equals與hashCode方法判斷元素是否重複,TreeSet是通過comparato的返回值來判斷元素是否重複以及排序的規則的;

                            5>、TreeSet儲存自定義型別的物件,自定義的類必須實現comparato方法,否則無法判斷元素的“大小”(排序規則);

                            6>、comparato的返回值為0,則不儲存元素,返回值為1,則認為儲存值與比較值相比較大,若返回值為-1則認為,儲存值與比較值相比較小;

                            7>、TreeSet的排序規則分為倆種,自然排序與定製排序,自然排序就是按照從小到大的順序排序,定製排序則是按照自己的規則排序;

5、Map集合的相關問題:

     (1)Map集合的典型實現

                1>、HashMap:底層採用hash表演算法,key的順序與hashSet一致,不會保證新增的順序;

                2>、TreeMap:底層紅黑樹演算法,排序規則按照自然排序或者定製順訊;

                3>、LinkedHashMap:採用連結串列演算法和雜湊演算法,保證元素的新增順序;

                4>、HashTable:採用雜湊表演算法,基本功能與hashMap類似,但是會保證插入的順序,且為執行緒同步的,key鍵不能為null,且效率低下(一個執行緒對其做put處理時,其他執行緒不僅不嫩使用put且不能使用get,造成執行緒的阻塞)jdk5之後提供了ConcurrentHashMap,是HashTable的擴充套件版本;

                5>、Properties:HashTable的子類,用來載入properties檔案的;

     (2)HashMap與HashTable的區別?

                 1>、倆者幾乎相同,但是會保證插入的順序(且不能保證隨著時間的推移,元素順序不變),且為執行緒同步,jdk5之後出了ConcurrentHashMap,是HashTable的擴充套件;

                 2>、HashMap使用的迭代器是Iterator是fail-fast(但是其remove方法是不會丟擲fail-fast,且不是必然發生的),而HashTable使用的enumerator迭代器不是fail-fast的;

                 3>、HashMap在單執行緒的效能要超過HashTable;

      (3)HashMap的實現原理?

                  1>、map集合:

                             嚴格意義上來說map並不是集合,而是倆個集合之間的對映關係;

                             並未實現collection介面也未實現Iterable介面,因此不能採用forEach遍歷;

                             是Entry(key,value),map可以看成是由多個Entry組成的;

                  2>、HashMap的實現原理:

                             是基於雜湊表演算法+陣列實現的;

                             HashMap在儲存物件時是將key-value當做一個整體進行處理的,這個整體就是一個Node物件,儲存物件時,先呼叫key的hash演算法來決定其在陣列中的位置,在根據equals演算法決定其在該陣列連結串列(bucket)上的位置;取物件時,先得到key的hashCode值,在根據equals方法從該位置上的連結串列中取出該Node;

                              使用了fail-fast機制;

                 3>、Map與set的關係?

                               hashSet、hashMap採用的底層演算法都是hash表演算法,treeSet與treeMap採用的都是紅黑樹演算法;

                               set集合就是由map集合的key組成的;

       (4)ConcurrentHashMap

                同步機制:使用分段鎖技術------結構與HashMap類似,採用的是陣列+連結串列的方式,分段鎖是將集合分為一段一段的segment然後給每一段segment分配一個鎖,當一個縣城訪問一個segment時,其他的分段也能被其他執行緒訪問,即可以實現並行插入;

                組成結構:一個ConcurrentHashMap是一個segment陣列,一個segment是一個hashEntry陣列,而每個hashEntry都是連結串列結構的元素,用來封裝雜湊對映表中的鍵值對;

                應用場景:多執行緒的寫

                             get不加鎖,定位到segment之後找到頭節點進行去取操作,value是通過volatile修飾的;

                             put加鎖,新增到hash連結串列的頭部;

                             remove加鎖,由於next是final型別的,所以必須把刪除之前的節點都複製一遍;

              ps:ConcurrentHashMap只能保證每一個呼叫是原子性的,但是不能保證多次的呼叫也是原子性的(這句話不太懂,如果有人知道的話請指導一下)