1. 程式人生 > >Java常見小知識點(持續更新...)

Java常見小知識點(持續更新...)

HR toarray 私有 事情 一個 xms 指示器 跳轉 nbsp

1.在什麽場景下需要重寫hashcode?HashMap的實現原理?

  • 如果我們對equals()方法進行了重寫,一般對hashcode進行重寫,保證相同的對象返回相同的hash值
  • HashMap實際上是一個"鏈表散列"的數據結構,即數組和鏈表的組合
  • 當我們向HashMap中put值的時候,先計算key的hash值,再根據hash值來計算出這個key在數組中的下標(通過hash與數組長度-1的位與運算,也正是因此,map長度都是2的次方,因為要保證length-1 都是 )如果數組該位置上已經存放有其他元素了,那麽在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。如果數組該位置上沒有元素,就直接將該元素放到此數組中的該位置上
  • 默認長度是16,負載因子0.75

2.ConcurrentHashMap

ConcurrentHashMap把Map分成了幾個segment,put和get的時候都根據key的hash,來計算在哪個segment中,每個segment類似於一個HashTable,都是線程安全的

3.容器

(1) java中,如果有一個類用來存放其他類的對象,這個類就叫容器,或者集合。集合就是講若幹性質相同或相近的類集合在一起而形成的整體。
之所以需要容器,是因為數組的長度難以擴充,數組中數據類型必須相同

(2) 容器和數組的區別

  • 容器沒有下標
  • 數組的功能都可以用ArrayList來實現
  • 可用toArrayList返回數組

4.ArrayList和LinkedList的區別

ArrayList基於數組,查找速度比較快,LinkedList基於鏈表,增刪操作比較快

5.set防重

  • HashSet不存入重復元素的規則.使用hashcode和equals,若計算出來一樣,則加入失敗
  • reeSet紅-黑樹的數據結構,默認對元素進行自然排序。如果在比較的時候兩個對象返回值為0,那麽元素重復

6.Collection包裝線程安全

Collections.synchronizedList(new ArrayList());
Collections.synchronizedSet(new HashSet());

7.JVM內存模型

JVM定義了若幹個程序執行期間使用的數據區域,主要分為 方法區、堆、虛擬機棧、本地方法棧、程序計數器

7.1 程序計數器

程序計數器是一塊較小的內存空間,可以看做是當前線程所執行的字節碼的行號指示器。分支、循環、異常跳轉等基礎功能依靠它。
如果執行的是一個Java方法,計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果執行的是一個本地方法,這個計數器為空。

7.2 虛擬機棧

線程私有,生命周期與線程相同。虛擬機棧描述的是Java方法執行的內存模型:每個方法被執行的同時都會創建一個棧幀,
用於存放方法的局部變量表,操作棧,動態鏈接,方法出口等信息,Java方法從調用直至執行完成,就是一個幀棧在虛擬機棧中的入棧出棧過程

  • 局部變量表: 用於存放方法參數和方法內部定義的局部變量
  • 操作數棧:和局部變量表一樣,操作數棧也是被組織成一個以字長為單位的數組,但是不是通過索引來獲取值,是通過入棧、出棧來進行數據的
    訪問。

  • 動態鏈接:虛擬機在運行時,常量池會保存大量的符號引用。如果是在類加載階段或者第一次使用時轉化為直接應用,則成為靜態解析,
    否則 成為動態鏈接。

  • 返回地址:一種是正常退出,退出後會根據方法的定義來決定是否要傳返回值給上層的調用者,一種是異常導致的方法結束,這種情況是不會傳返回值給上層的調用方法。
    方法的的一次調用就對應著棧幀在虛擬機棧中的一次入棧出棧操作,因此方法退出時可能做的事情包括:恢復上層方法的局部變量表以及操作數棧,如果有返回值的話,就把返回值壓入到調用者棧幀的操作數棧中,還會把PC計數器的值調整為方法調用入口的下一條指令。

7.3 本地方法棧

與虛擬機棧類似,虛擬機棧是為了執行Java方法而存在的,本地方法棧是為了執行native方法入棧出棧的

7.4 堆

是JVM所管理的內存中最大的一塊。被所有線程共享,在虛擬機啟動時創建,用於存放對象實例,-Xms(最小值)和-Xmx(最大值),默認是計算機物理內存的1/64
堆是GC主要活動的區域,因為GC基本采用分代收集算法,因此又分為新生代和老年代。新生代,程序新創建的對象都是從新生代分配內存,經過多次GC仍然存貨的對象會進入老年代,
新建的對象也可能直接進入老年代,大對象或者大的數組對象,且數組內部無引用外部對象

7.5 方法區

存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據

8. GC算法相關

GC一般系統隨機觸發以及system.gc(),且當eden分配新對象而內存不足時觸發minorgc,或者eden向old轉移但是old內存不夠時觸發fullgc
對於新生代,一般采用復制算法,一般內存劃分為一個較大的eden和2個survivor,每次使用eden和1個survivor,默認8:1,每次講eden和survivor中存活的對象存入另一個survivor,
需要老年代擔保(Handle Promotion)
對於老年代,一般采用標記-整理算法,講可用對象向內存的一邊偏移,然後清除掉邊界以外的內存

9. GC時候如何判斷一個對象為垃圾

可以通過引用計數器來判斷,但是無法解決循環引用的問題
可達性分析法,GC root與這個對象沒有可達路徑

循環引用demo如下

Class C {
    public Object x;  
}
C obj1、obj2 = new C(); 
obj1.x = obj2; 
obj2.x = obj1; 
obj1、obj2 = null; 

這種情況下,obj1和obj2的計數器都不為0

10.sql優化

  • 盡量避免全表掃描,盡量在where和order by上建立索引
  • where中避免null的判斷、少使用!=或者<>操作符,避免or 換成union all,少用in可用exists代替,where字句中少用函數

Java常見小知識點(持續更新...)