Java面試題 - 基礎題

01 接口和抽象類的區別

  • ⼀個類聲明可否既是abstract的,⼜是final的? 不能,這兩個修式符⽭盾(abstract就是要被繼承)
  • 抽象類不⼀定包含抽象⽅法
  • 有抽象⽅法,則⼀定是抽象類
  • 抽象類不能被實例化,⼀般⽤作基類使⽤;
  • 類可以實現多個接⼝但只能繼承⼀個抽象類
  • 接⼝⾥⾯所有的⽅法都是Public的,抽象類允許private、protected⽅法
  • JDK8前接⼝⾥⾯所有的⽅法都是抽象的且不允許有靜態⽅法,抽象類可以有普通、靜態⽅法,JDK8 接⼝可以實現默認⽅法和靜態⽅法,前⾯加default、static關鍵字。

02 java中的異常有哪⼏類,分別怎麼使⽤?

在這裏插入圖片描述
分爲錯誤和異常,異常⼜包括運⾏時異常、⾮運⾏時異常
錯誤:如StackOverflowError、OutOfMemoryError
異常

  • 運⾏時異常,如NullPointerException、IndexOutOfBoundsException,都是RuntimeException及其⼦類。
  • ⾮運⾏時異常,如IOException、SQLException,都是Exception及其⼦類,這些異常是⼀定需要try catch捕獲的。

03 常⽤的集合類有哪些?⽐如list如何排序?

主要分爲三類,Map、Set、List:

  • Map: HashMap、LinkedHashMap、TreeMap
  • Set:HashSet、LinkedHashSet、TreeSet
  • List: ArrayList、LinkedList
Collections.sort(list);

04 ArrayList和LinkedList內部實現⼤致是怎樣的?他們之間的區別和優缺點?

  • ArrayList:內部使⽤數組的形式實現了存儲,利⽤數組的下標進⾏元素的訪問,因此對元素的隨機訪問速度⾮常快。因爲是數組,所以ArrayList在初始化的時候,有初始⼤⼩10,插⼊新元素的時候,會判斷是否需要擴容,擴容的步⻓是0.5倍原容量,擴容⽅式是利⽤數組的複製,因此有⼀定的開銷。
  • LinkedList:內部使⽤雙向鏈表的結構實現存儲,LinkedList有⼀個內部類作爲存放元素的單元,⾥⾯有三個屬性,⽤來存放元素本身以及前後2個單元的引⽤,另外LinkedList內部還有⼀個header屬性,⽤來標識起始位置,LinkedList的第⼀個單元和最後⼀個單元都會指向header,因此形成了⼀個雙向的鏈表結構。
  • ArrayList查找較快,插⼊、刪除較慢,LinkedList查找較慢,插⼊、刪除較快。

05 內存溢出是怎麼回事?舉個例⼦?

內存溢出 out of memory,是指程序在申請內存時,沒有⾜夠的內存空間供其使⽤,出現out of memory,例如:

List<Object> list = new ArrayList<>(); 2 while (true) { 3 list.add(new Object()); 4 }

內存溢出可能的原因:

  • 程序中存在死循環
  • 靜態變量和靜態⽅法太多了
  • 內存泄漏:⽐如說⼀個靜態的list,⼀直往⾥放值,⼜因爲靜態變量不會被釋放,所以遲早是要內存溢出的。
  • ⼤對象過多:java中的⼤對象是直接進⼊⽼年代的,然後當多個⼤對象同時⼯作時造成程序的可⽤內存⾮常⼩,⽐如list中原本最多可以放1000個對象,因爲可⽤內存太⼩,放了500個就放不下了。
  • 程序分配內存過⼩:還有⼀種很常⻅的情況,在把⼀個很⼤的程序直接導⼊,直接就內存溢出了,原因就是內存相對這個程序就是太⼩了,需要⼿動增加內存。
  • 內存泄漏 memory leak,是指程序在申請內存後,⽆法釋放已申請的內存空間,⼀次內存泄漏危害可以忽略,但內存泄漏堆積後果很嚴重,⽆論多少內存,遲早會被佔光。

06 ==和equals的區別

  • == 是運算符,⽽equals是Object的基本⽅法
  • == ⽤於基本類型的數據的⽐較,或者是⽐較兩個對象的引⽤是否相同,equals⽤於⽐較兩個對象的值是否相等,例如字符串的⽐較。

07 hashCode方法的作用

  • hashCode的存在主要是⽤於查找的快捷性,爲了配合基於散列的集合正常運⾏,如Hashtable,HashMap等,hashCode是⽤來在散列存儲結構中確定對象的存儲地址的;
  • 如果兩個對象相同,就是適⽤於equals(java.lang.Object) ⽅法,那麼這兩個對象的hashCode⼀定要相同;
  • 如果對象的equals⽅法被重寫,那麼對象的hashCode也儘量重寫,並且產⽣hashCode使⽤的對象,⼀定要和equals⽅法中使⽤的⼀致,否則就會違反上⾯提到的第2點;
  • 兩個對象的hashCode相同,並不⼀定表示兩個對象就相同,也就是不⼀定適⽤於equals(java.lang.Object) ⽅法,只能夠說明這兩個對象在散列存儲結構中,它們存放在同⼀個桶⾥⾯。

08 NIO是什麼?適用於何種場景?

  1. NIO是爲了彌補IO操作的不⾜⽽誕⽣的,NIO的⼀些新特性有:⾮阻塞I/O,選擇器,緩衝以及管道。
  2. 如果需要管理同時打開的成千上萬個連接,這些連接每次只是發送少量的數據,例如聊天服務器,這時候⽤NIO處理數據可能是個很好的選擇。(適⽤於⼩數據多連接)
  3. ⽽如果只有少量的連接,⽽這些連接每次要發送⼤量的數據,這時候傳統的IO更合適。使⽤哪種處理數據,需要在數據的響應等待時間和檢查緩衝區數據的時間上作⽐較來權衡選擇。
  • NIO概念:NIO(new IO),是⼀種⾮阻塞式I/O;java NIO採⽤了雙向通道進⾏數據傳輸,在通道上我們可以註冊我們感興趣的事件:連接事件、讀寫事件;NIO主要有三⼤核⼼部分:Channel(通道),Buffer(緩衝區), Selector(選擇器)。傳統IO基於字節流和字符流進⾏操作,⽽NIO基於Channel和Buffer(緩衝區)進⾏操作,數據總是從通道讀取到緩衝區中,或者從緩衝區寫⼊到通道中。Selector(選擇區)⽤於監聽多個通道的事件(⽐如:連接打開,數據到達)。因此,單個線程可以監聽多個數據通道。
  • NIO原理:
  1. 由⼀個專⻔的線程來處理所有的 IO 事件,並負責分發。
  2. 事件驅動機制:事件到的時候觸發,⽽不是同步的去監視事件。
  3. 線程通訊:線程之間通過 wait,notify 等⽅式通訊, 保證每次上下⽂切換都是有意義的。減少⽆謂的線程切換。
    在這裏插入圖片描述

09 HashMap實現原理?如何保證HashMap線程安全?

  1. HashMap簡單說就是它根據鍵的hashCode值存儲數據,⼤多數情況下可以直接定位到它的值,因⽽具有很快的訪問速度,但遍歷順序卻是不確定的。
  2. HashMap基於哈希表,底層結構由數組來實現,添加到集合中的元素以“key–value”形式保存到數組中,在數組中key–value被包裝成⼀個實體來處理—也就是上⾯Map接⼝中的Entry。
  3. 在HashMap中,Entry[]保存了集合中所有的鍵值對,當我們需要快速存儲、獲取、刪除集合中的元素時,HashMap會根據hash算法來獲得“鍵值對”在數組中存在的位置,以來實現對應的操作⽅法。在這裏插入圖片描述
  4. HashMap底層是採⽤數組來維護的.Entry靜態內部類的數組在這裏插入圖片描述
  5. HashMap添加元素:將準備增加到map中的對象與該位置上的對象進⾏⽐較(equals⽅法),如果相同,那麼就將該位置上的那個對象(Entry類型)的value值替換掉,否則沿着該Entry的鏈繼續重複上述過程,如果到鏈的最後任然沒有找到與此對象相同的對象,那麼這個時候就會被增加到數組中,將數組中該位置上的那個Entry對象鏈到該對象的後⾯(先hashcode計算位置,如果找到相同位置便替換值,找不到則重複hashcode計算,直到最後在添加到hashmap最後⾯;)在這裏插入圖片描述
  6. HashMap是基於哈希表的Map接⼝的⾮同步實現,允許null鍵值,但不保證映射的順序;底層使⽤數組實現,數組中的每項是⼀個鏈表;存儲時根據key的hash算法來決定其存儲位置;數組擴容需要重新計算擴容後每個元素在數組中的位置很耗性能;
  7. ConcurrentHashMap是HashMap的線程安全實現,允許多個修改操作同時進⾏(使⽤了鎖分離技術),它使⽤了多個鎖來控制對hash表的不同段進⾏的修改,每個段其實就是⼀個⼩的hashtable,它們有⾃⼰的鎖。使⽤了多個⼦hash表(段Segment),允許多個讀操作併發進⾏,讀操作並不需要鎖,因爲它的HashEntry⼏乎是不可變的:

10 jvm內存結構?爲什麼需要GC?

  • 內存結構:在這裏插入圖片描述
  • 垃圾回收:垃圾回收可以有效的防⽌內存泄漏,有效的使⽤可以使⽤的內存。垃圾回收器通常是作爲⼀個單獨的低優先級的線程運⾏,不可預知的情況下對內存堆中已經死亡的或者⻓時間沒有使⽤的對象進⾏清除和回收,程序員不能實時的調⽤垃圾回收器對某個對象或所有對象進⾏垃圾回收。回收機制有分代複製垃圾回收、標記垃圾回收、增量垃圾回收等⽅式。

11 NIO模型,select/epoll的區別,多路復⽤的原理?

io多路復⽤:

  • 概念:IO多路復⽤是指內核⼀旦發現進程指定的⼀個或者多個IO條件準備讀取,它就通知該進程。
  • 優勢:與多進程和多線程技術相⽐,I/O多路復⽤技術的最⼤優勢是系統開銷⼩,系統不必創建進程/線程,也不必維護這些進程/線程,從⽽⼤⼤減⼩了系統的開銷。
  • 系統:⽬前⽀持I/O多路復⽤的系統調⽤有 select,pselect,poll,epoll。

select:

  • select⽬前⼏乎在所有的平臺上⽀持,其良好跨平臺⽀持也是它的⼀個優點。select的⼀個缺點在於單個進程能夠監視的⽂件描述符的數量存在最⼤限制,在Linux上⼀般爲1024,可以通過修改宏定義甚⾄重新編譯內核的⽅式提升這⼀限制,但是這樣也會造成效率的降低。

poll:

它沒有最⼤連接數的限制,原因是它是基於鏈表來存儲的,但是同樣有⼀個缺點:

  • ⼤量的fd的數組被整體複製於⽤戶態和內核地址空間之間,⽽不管這樣的複製是不是有意義。
  • poll還有⼀個特點是“⽔平觸發”,如果報告了fd後,沒有被處理,那麼下次poll時會再次報告該fd。

epoll跟select都能提供多路I/O復⽤的解決⽅案。在現在的Linux內核⾥有都能夠⽀持,其中epoll是Linux所特有,⽽select則應該是POSIX所規定,⼀般操作系統均有實現。

12 ava中⼀個字符佔多少個字節?int,long,double佔多少個字節?

  • 1字節: byte , boolean
  • 2字節: short , char
  • 4字節: int , float
  • 8字節: long , double

13 創建⼀個類的實例都有哪些⽅法?

在這裏插入圖片描述

14 final/finaly/finalize區別?

  • final是定義類、⽅法、字段的修飾符,表示類不可被繼承,⽅法不能被重寫,字段值不能被修改
  • finally是異常處理機制的關鍵字,表示最後執⾏
  • finalize是Object的⼀個⽅法,在對象被虛擬機回收時會判斷是否執⾏該⽅法,當對象沒有覆蓋finalize⽅法,或者finalize⽅法已經被虛擬機調⽤過,虛擬機將這兩種情況都視爲“沒有必要執⾏”。

15 Session/Cookie區別?

  • Session存儲在服務器端,類型可以是任意的Java對象,Cookie存儲在客戶端,類型只能爲字符串。

16 String/StringBuffer/StringBuilder的區別以及實現?

  • String、StringBuffer是線程安全的,StringBuilder不是線程安全。
  • String不繼承任何類,StringBuffer、StringBuilder繼承⾃AbstractStringBuilder。
  • StringBuffer線程安全但效率低,應該使⽤在多線程情況下。
  • StringBuilder線程不安全,在單線程情況下效率⾼。

17 Servlet⽣命週期

Servlet⽣命週期分爲三個階段:

  1. 初始化階段 調⽤init()⽅法
  2. 響應客戶請求階段  調⽤service()⽅法
  3. 終⽌階段  調⽤destroy()⽅法

18 如何⽤java分配⼀段連續的1G的內存空間?需要注意些什麼?

ByteBuffer.allocateDirect(1024*1024*1024);

要注意內存溢出問題。

19 Java有⾃⼰的內存回收機制,但爲什麼還存在內存泄漏的問題呢?

⾸先內存泄漏 memory leak,是指程序在申請內存後,⽆法釋放已申請的內存空間,⼀次內存泄漏危害可以忽略,但內存泄漏堆積後果很嚴重,⽆論多少內存,遲早會被佔光。

⽐如下⾯這段代碼,list持有o的引⽤,o暫時是⽆法被JVM垃圾回收的,只有當list被垃圾回收或者o從對象list刪除掉後,o才能被JVM垃圾回收:
在這裏插入圖片描述

20 什麼是java序列化,如何實現java序列化(寫⼀個例⼦)

  • 原理:將對象寫⼊流中,再從流中還原.ObjectOutPutStream
  • 對象中的成員對象也是可序列化的,但可通過transient關鍵字標示不序列化
  • 通過序列化進⾏深拷⻉,從流中還原對象
  • 序列化作⽤:對象保存(保存爲⼀組字節,只保存對象的成員變量);當使⽤RMI(遠程⽅法調⽤),或者在⽹絡中傳遞對象時,都會使⽤對象序列化;
  • serialVersionUID 主要是解決序列化後與再反序列化時有修改的不兼容問題.

序列化⼆叉樹:

private int index = -1; 
String Serialize(TreeNode root) { 
	 StringBuilder sb = new StringBuilder(); 
	 if (root == null) { 
	  sb.append("#,"); 
	   return sb.toString(); 
	  } 
	  sb.append(root.val + ","); 
	  sb.append(Serialize(root.left));
      sb.append(Serialize(root.right));
      return sb.toString();
}

 TreeNode Deserialize(String str) {
    index++;
    String[] strs = str.split(",");
    if (index > strs.length || strs[index].equals("#")) {
        return null;
     }
    TreeNode root = new TreeNode(Integer.parseInt(strs[index])); 
    root.left = Deserialize(str);
    root.right = Deserialize(str);
    return root;
}

21 String s = new String(“abc”)創建了⼏個String Object?

  • 2個,會創建String對象在常量池和堆中。
  • String中的intern(),⾸先檢查String pool是否有對應的字符串對象,如果有則返回,如果沒有則在String pool中⽣成字符串,並返回地址;
  • String中字⾯值”ab"之間拼接是在String pool中產⽣,⽽字⾯值與變量拼接字符串或者new String(“")則是在堆中產⽣對象;

22 靜態對象

  1. 在main⽅法開始運⾏時需要注意static的先後順序:靜態變量和靜態代碼塊(按代碼先後順序)—-匿名塊和成員變量(按代碼先後順序)—-構造函數—靜態⽅法(調⽤時加載)
  2. 先執⾏⽗類的靜態塊,再執⾏⼦類的靜態塊,再執⾏⽗類的構造⽅法,再執⾏⼦類的構造⽅法
  • ------靜態塊>構造⽅法
  • ------⽗>⼦

23 final關鍵字

  1. ⽤在類上不能被繼承,abstract(需要被繼承)和final不能共存;
  2. ⽤在⽅法上不能被重寫
  3. ⽤在變量上表示⽅變量不能被改變

對於final類的成員變量的初使化⽅式(基本數據類型):

  1. 申明變量時直接賦值
  2. 在構造⽅法中完成賦值,如果有多個構造⽅法,則每個都要完成final類變量的賦值
  3. 如果⼀個變量爲static final則只能在申明時賦值

對於final類型的引⽤變量來說,所謂的不能改變指的是該引⽤不能改變,值是可以改變的(如StringBuffer)

爲什麼⼀般在public類final終態成員變量申明時要加static?

  • static對象存放在靜態空間,不會在運⾏時被釋放,可以節省內存,類的多個對象同時引⽤只有⼀份,沒有多份拷⻉。

24 HashMap與HashTable的區別

  1. 線程安全上,hashtable是同步的線程安全;hashmap是⾮同步的線程不安全,可接受null的值和value(hashtable不允許);
  2. 對單線程來說,hashTable效率低
  3. 線程安全的類:vector(⽐arrayList多了同步機制,效率低不建議使⽤)、stack(堆棧類,先進後出)、hashtable(⽐hashmap多了同步機制)、enumeration(枚舉類)。

25 多態

  • 多態條件:1.有繼承 2. 有重寫 3. 要有⽗類引⽤指向⼦類對象;如Animal a = new Tiger();
  • ⽗類或者接⼝引⽤指向⼦類或者實現該接⼝的類的對象;
  • 多態是運⾏時⾏爲,不是編譯時⾏爲;
  • 多態要有動態綁定,通過⽅法重寫與⽅法重載來實現多態?? 這種說法是錯誤,因爲⽅法重載是編譯期決定好的,沒有後期也就是運⾏期的動態綁定;

26 集合刪除

注意: List底層爲數組,刪除時數組元素下標會被改變

  1. 迭代器調⽤.next()⽅法時,會檢測是否有被修改過
  2. 如果要刪除集合中的元素⼀定要⽤跌代器的remove()⽅法.

27 參數傳遞與引⽤傳遞

  1. 基本數據類型傳參,是數據值的拷⻉互不影響.
  2. 引⽤對象傳參,是傳地址,兩個引⽤指向同⼀個對象,則對象改變兩個引⽤也都改變(java編程只有值傳遞參數)

28 hash衝突

描述:當關鍵字值域遠⼤於哈希表的⻓度,⽽且事先並不知道關鍵字的具體取值時,衝突就難免會發⽣(兩個或兩個以上的值hash計算的結果有相同的,造成衝突) 。

解決⽅法:

  1. 開放地址法:插⼊元素時,如果發⽣衝突,算法會簡單的從該槽位置向後循環遍歷hash表,直到找到表中的下⼀個空槽,並將該元素放⼊該槽中(會導致相同hash值的元素挨在⼀起和其他hash值對應的槽被佔⽤)。查找元素時,⾸先散列值所指向的槽,如果沒有找到匹配,則繼續從該槽遍歷hash表,直到:(1)找到相應的元素;(2)找到⼀個空槽,指示查找的元素不存在,(所以不能隨便刪除元素);(3)整個hash表遍歷完畢(指示該元素不存在並且hash表是滿的)
  2. 鏈地址法:現⾏探測法的基本思想是將所有哈希地址爲i的元素構成⼀個稱爲同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,因⽽查找、插⼊和刪除主要在同義詞鏈中進⾏。鏈地址法適⽤於經常進⾏插⼊和刪除的情況。
  3. 在散列(雙/多重散列):當發⽣衝突時,使⽤第⼆個、第三個、哈希函數計算地址,直到⽆衝突時。缺點:計算時間增加。
  4. 建⽴⼀個公共溢出區:假設哈希函數的值域爲[0,m-1],則設向量HashTable[0…m-1]爲基本表,另外設⽴存儲空間向量OverTable[0…v]⽤以存儲發⽣衝突的記錄。

29 在java中⼀個字符能否表示⼀個漢字

在java中,⼀個字符表示16位,相當於2個字節,⼀個漢字正好是2個字節。

30 ⼀致性hash

⼀致性hash算法:我們的memcached客戶端(這⾥我看的spymemcache的源碼),使⽤了⼀致性hash算法ketama進⾏數據存儲節點的選擇。與常規的hash算法思路不同,只是對我們要存儲數據的key進⾏hash計算,分配到不同節點存儲。⼀致性hash算法是對我們要存儲數據的服務器進⾏hash計算,進⽽確認每個key的存儲位置。這⾥提到的⼀致性hash算法ketama的做法是:選擇具體的機器節點不在只依賴需要緩存數據的key的hash本身了,⽽是機器節點本身也進⾏了hash運算。

  1. ⼀致性hash算法是分佈式系統中常⽤算法,設計⽬的是爲了解決因特⽹中的熱點(hot spot)問題。解決了P2P環境最爲關鍵問題—如何在動態⽹絡拓撲中分佈存儲和路由;
  2. ⼀致性hash算法引⼊虛擬節點機制,解決服務節點少時數據傾斜問題(即對每⼀個服務節點計算多個哈希,每個計算結果位置都放置⼀個此服務節點,稱爲虛擬節點。);

**具體做法:**如果有⼀個寫⼊緩存的請求,其中Key值爲K,計算器hash值Hash(K), Hash(K) 對應於圖 – 1環中的某⼀個點,如果該點對應沒有映射到具體的某⼀個機器節點,那麼順時針查找,直到第⼀次找到有映射機器的節點,該節點就是確定的⽬標節點,如果超過了2^32仍然找不到節點,則命中第⼀個機器節點。⽐如 Hash(K) 的值介於A~B之間,那麼命中的機器節點應該是B節點。

數據保存流程:

  1. ⾸先求出memcached服務器(節點)的哈希值,並將其配置到0~232的圓(continuum)上。
  2. 然後採⽤同樣的⽅法求出存儲數據的鍵的哈希值,並映射到相同的圓上。
  3. 然後從數據映射到的位置開始順時針查找,將數據保存到找到的第⼀個服務器上。如果超過232仍然找不到服務器,就會保存到第⼀臺memcached服務器上。

在這裏插入圖片描述

31 Java反射機制

可以在運⾏時判斷⼀個對象所屬的類,構造⼀個類的對象,判斷類具有的成員變量和⽅法,調⽤1個對象的⽅法。

4個關鍵的類:Class,Constructor,Field,Method。 getConstructor獲得構造函數/getDeclardConstructor;getField/getFields/getDeclardFields獲得類所⽣命的所有字段;getMethod/getMethods/getDeclardMethod獲得類聲明的所有⽅法,正常⽅法是⼀個類創建對象,⽽反射是1個對象找到1個類。

32 冪等的處理⽅式

描述:接⼝可重複調⽤,在調⽤⽅多次調⽤的情況下,接⼝最終得到的結果是⼀致的。

  1. 查詢操作是天然冪等
  2. 唯⼀索引,防⽌新增髒數據
  3. token機制,防⽌⻚⾯重複提交
  4. 悲觀鎖 for update
  5. 樂觀鎖(通過版本號/時間戳實現, 通過條件限制where avai_amount-#subAmount# >= 0)
  6. 分佈式鎖
  7. 狀態機冪等(如果狀態機已經處於下⼀個狀態,這時候來了⼀個上⼀個狀態的變更,理論上是不能夠變更的,這樣的話,保證了有限狀態機的冪等。)

33 hashmap在jdk1.8中的改動?

  1. Jdk1.8以前是進⾏四次擾動計算,可能從速度功效各⽅⾯考慮,jdk1.8變成擾動⼀次,低16位和⾼16位進⾏異或計算。取模的時候考慮取模運算的速度⽐較慢,改⽤與操作優化效率,很巧妙,hash table就沒設計的這麼好。
  2. JDK1.8⾥對hashmap最⼤的改變是引⼊了紅⿊樹,這⼀點在hash不均勻並且元素個數很多的情況時,對hashmap的性能提升⾮常⼤。Hashmap的底層實現是使⽤⼀個entry數組存儲,默認初始⼤⼩16,不過jdk8換了名字叫node,可能是因爲引⼊了樹,叫node更合適吧,另外我也不喜歡entry這個名字,不能望⽂⽣義,我在剛學的時候還以爲是什麼神祕的東⻄呢,其實就是個鍵值對對象⽽已。Node⾥有next引⽤指向下⼀個節點,因爲hashmap解決衝突的思路是拉鍊法。
  3. 另外變化⽐較⼤的還有擴容機制,也就是resize⽅法。

34 java 8 流式使⽤

List<Integer> evens = nums.stream().filter(num -> num % 2 == 0).collect(Collectors.toList()); 
//1、stream()操作將集合轉換成⼀個流,
//2、filter()執⾏我們⾃定義的篩選處理,這⾥是通過lambda表達式篩選出所有偶數,
//3、最後我們通過collect()對結果進⾏封裝處理,並通過Collectors.toList()指定其封裝成爲⼀個List集合返回。

35 java 域的概念

field,域是⼀種屬性,可以是⼀個類變量,⼀個對象變量,⼀個對象⽅法變量或者是⼀個函數的參數。

36 jdk1.8中ConcurrentHashMap size⼤於8時會轉化成紅⿊樹,請問有什麼作⽤,如果通過remove操作,size⼩於8了,會發⽣什麼?

put時如果鏈表size>=8並且table.length>=64,這時鏈表會轉變成⼀個紅⿊樹(紅⿊樹是⼀個⾃平衡的⼆叉查找樹,查找效率會從鏈表的o(n)降低爲o(logn),效率是⾮常⼤的提⾼),但是remove不會逆轉。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章