一、接口和抽象類的區別
- 抽象類中可以含有構造方法,而接口內不能有。
- 抽象類中可以有普通成員變量,而接口中不能有。
- 抽象類中可以包含非抽象的普通方法,而接口中所有方法必須是抽象的,不能有非抽象的普通方法。
- 抽象類中的抽象方法的訪問類型可以是public、protected和默認類型,但接口中的抽象方法只有public和默認類型。
- 抽象類中可以包含靜態方法,接口內不能包含靜態方法。
- 抽象類和接口中都可以包含靜態成員變量,抽象類中的靜態成員變量的訪問類型可以是任意,但接口中定義的變量只能是public static類型,並且默認為public static類型。
- 一個類可以實現多個接口,但只能繼承一個抽象類。
- 接口更多的是在系統框架設計方法發揮作用,主要定義模塊之間的通信,而抽象類在代碼實現方面發揮作用,可以實現代碼重用。
二、java虛擬機的運行時數據區有幾塊?線程私有和線程共享區域有哪些?
- 程序計數器:線程私有,當前線程執行的字節碼的行號指示器。
- 虛擬機棧:線程私有,存放基本數據類型、對象引用和returnAddress類型。
- 本地方法棧:為虛擬機使用到的Native方法服務。
- java堆:線程共享,存放對象的實例,也是GC回收器管理的主要區域。
- 方法區:線程共享,存放已被虛擬機加載的類信息、常量、靜態變量、即時編譯后的代碼等數據。
- 運行時常量池:方法區的一部分,存放編譯期生成的各種字面量和符號引用。
- 直接內存:不是虛擬機運行時數據區的一部分,也不是java虛擬機規范中定義的內存區域,容易引起OOM異常,NIO會調用,不受Java堆大小的限制。
三、HashMap與HashTable的區別?
- HashTable是基於陳舊的Dictionary類的,HashMap是Java1.2引進的Map接口的一個實現。
- HashTable的方法是同步的,而HashMap的方法不是,因此HashTable是線程安全的,但是代碼的執行效率上要慢於HashMap。
- HashMap允許空值和空鍵,但是HashTable不可以。
- HashMap非同步實現Map接口,是一個【鏈表數組】的數據結構,最大承載量是16,可以自動變長,由Entry[]控制(key、value、next),hashCode() 判斷key是否重復。
- 建議:如果需要做同步,使用ConcurrentHashMap,降低了鎖的粒度。在HashMap的基礎上,ConcurrentHashMap將數據分為多個segment,默認為16個(concurrency level),然后每次操作對一個segment加鎖,避免多線程鎖的幾率,提高並發效率。這里在並發讀取時,除了key對應的value為null之外,並沒有使用鎖。
四、ArrayList和LinkedList的區別?
- ArrayList基於數組實現,LinkedList基於鏈表實現ArrayList增加和刪除比LinkedList慢,但是LinkedList在查找的時候需要遞歸查找,效率比ArrayList慢。關於多線程方面,如果要求線程安全的,有一個Vector,不過比較多的使用是CopyOnWriteArrayList代替ArrayList,CopyOnWriteArrayList適合使用在讀操作遠遠大於寫操作的場景中,比如緩存。發生修改時做copy,新老版本分離,保證讀的高性能,適用於以讀為主的情況。
五、Set接口
- HashSet是Set接口的典型實現,HashSet使用hash算法來存儲元素,因此具有很好的存取和查找性能。缺點:無法保證元素的排列順序,順序有可能發生變化;HashSet是異步的;集合元素值可以是null;當向HashSet集合中存入一個元素時,HashSet會調用該對象的hashCode() 方法來得到該對象的hashCode值,然后根據該HashCode值來確定該對象在HashSet中存儲的位置。HashSet還有一個子類LinkedHashSet,其集合也是根據元素hashCode值來決定元素存儲位置,但它同時用鏈表來維護元素的次序,這樣使得元素看起來是以插入的順序保存的,也就是說,當遍歷LinkedHashSet集合元素時,它將會按元素的添加順序來訪問集合中的元素。所以LinkedHashSet的性能略低於HashSet,但在迭代訪問全部元素時將有很好的性能,因為它以鏈表維護內部順序。
- TreeSet是SortSet接口的唯一實現,TreeSet可以確保集合元素處於排序狀態。TreeSet不是根據元素插入順序進行排序的,而是根據元素的值來排序。TreeSet支持兩種排序方法:自然排序和定制排序。
- EnumSet中所有值都必須是指定枚舉類型的值,它的元素也是有序的,以枚舉值在枚舉列的定義順序來決定集合元素的順序。EnumSet集合不允許加入null元素,否則拋出NPE(NullPointerException)異常。EnumSet類沒有暴露任何構造器來創建該類的實例,程序應該通過它提供的static方法來創建EnumSet對象。
- 總結:它們都是線程不安全的。Set是一種不包含重復元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2) = false,Set最多有一個null元素。A. HashSet的性能比TreeSet好,因為TreeSet需要額外的紅黑樹算法來維護集合元素的次序,只有當需要一個保持排序的Set時,才會用TreeSet。B. EnumSet是性能最好的,但它只能保存枚舉值。
- 關於HashSet,條目數和容量之和來講,迭代是線性的。因此,如果迭代性能很重要,那就應該慎重選擇一個適當的初始容量。容量選的太大,既浪費空間,也浪費時間。默認的初始容量是101,一般來講,它比你所需要的多。可以用int構造函數來指定初始容量。如下:
Set s = new HashSet(15)
六、Set中的區別
- HashSet是通過HashMap實現的,TreeSet是通過TreeMap實現的,只不過Set用的只是Map的key。
- Map的key和Set都有一個共同點就是集合的唯一性,TreeMap更多的是提供了一個排序的功能。
- hashCode() 和 equal() 是HashMap用的,因為無需排序所以主需要關注定位和唯一性即可。
- 說明:hashCode()是用來計算hash值的,hash值用來確定hash表的索引,hash表中的一個索引處存放的是一張鏈表,所以還需要用equal方法循環比較鏈上的每一個對象,才可以真正定位到鍵值對應的Entry。put時如果hash表中沒定位到,就在鏈表前加一個Entry,如果定位到了,則替換Entry中的value,並返回舊value。
- 由於TreeMap需要排序,所以需要一個Comparator為鍵值進行大小比較,當然也是用它定位的。說明:Comparator可以在創建TreeMap時指定;如果創建時沒有確定,那么就會使用key.compareTo()方法,這就要求key必須實現Comparable接口。TreeMap是使用Tree數據結構實現的,所以使用compare接口就可以完成定位了。