Java知識分享網 - 輕松學習從此開始!????

Java知識分享網

Java1234官方群25:java1234官方群25
Java1234官方群25:838462530
     

GIT視頻教程(結合github,碼云)免費領取

SpringBoot打造全棧在線教育平臺實戰課程

SpringBoot打造企業級進銷存

Java1234 VIP課程

領取微信掃碼登錄Java實現視頻教程

Java1234至尊VIP(特價活動)

阿里云Java中級筆試面試題 PDF 下載


分享到:
時間:2020-08-10 10:45來源:http://www.248787.tw 作者:小鋒  侵權舉報
阿里云Java中級筆試面試題 PDF 下載
失效鏈接處理
阿里云Java中級筆試面試題 PDF 下載



本站整理下載:
 
相關截圖:
 
主要內容:

List 和 Set 的區別 List , Set 都是繼承自 Collection 接口 List 特點:元素有放入順序,元素可重復 , Set 特點:元素無放入順序,元素不可重復,重復元素會覆蓋掉,(元素雖然無放入順序,但是元素在set中的位 置是有該元素的 HashCode 決定的,其位置其實是固定的,加入Set 的 Object 必須定義 equals ()方法 ,另外list
支持for循環,也就是通過下標來遍歷,也可以用迭代器,但是set只能用迭代,因為他無序,無法用下標來取得想 要的值。) Set和List對比 Set:檢索元素效率低下,刪除和插入效率高,插入和刪除不會引起元素位置改變。
List:和數組類似,List可以動態增長,查找元素效率高,插入刪除元素效率低,因為會引起其他元素位置改變 HashSet 是如何保證不重復的 向 HashSet 中 add ()元素時,判斷元素是否存在的依據,不僅要比較hash值,同時還要結合 equles 方法比較。 HashSet 中的 add ()方法會使用 HashMap 的 add ()方法。以下是 HashSet 部分源碼: HashMap 的 key 是唯一的,由上面的代碼可以看出 HashSet 添加進去的值就是作為 HashMap 的key。所以不會
重復( HashMap 比較key是否相等是先比較 hashcode 在比較 equals )。
HashMap 是線程安全的嗎,為什么不是線程安全的(最好畫圖說明多線程
環境下不安全)?
不是線程安全的;
如果有兩個線程A和B,都進行插入數據,剛好這兩條不同的數據經過哈希計算后得到的哈希碼是一樣的,且該位
置還沒有其他的數據。所以這兩個線程都會進入我在上面標記為1的代碼中。假設一種情況,線程A通過if判斷,該
位置沒有哈希沖突,進入了if語句,還沒有進行數據插入,這時候 CPU 就把資源讓給了線程B,線程A停在了if語句
里面,線程B判斷該位置沒有哈希沖突(線程A的數據還沒插入),也進入了if語句,線程B執行完后,輪到線程A執
行,現在線程A直接在該位置插入而不用再判斷。這時候,你會發現線程A把線程B插入的數據給覆蓋了。發生了線
程不安全情況。本來在 HashMap 中,發生哈希沖突是可以用鏈表法或者紅黑樹來解決的,但是在多線程中,可能
就直接給覆蓋了。
上面所說的是一個圖來解釋可能更加直觀。如下面所示,兩個線程在同一個位置添加數據,后面添加的數據就覆蓋
住了前面添加的。
private static final Object PRESENT = new Object(); private transient HashMap<E,Object> map; public HashSet() { map = new HashMap<>(); }public boolean add(E e) { return map.put(e, PRESENT)==null; }
如果上述插入是插入到鏈表上,如兩個線程都在遍歷到最后一個節點,都要在最后添加一個數據,那么后面添加數
據的線程就會把前面添加的數據給覆蓋住。則
在擴容的時候也可能會導致數據不一致,因為擴容是從一個數組拷貝到另外一個數組。
HashMap 的擴容過程
當向容器添加元素的時候,會判斷當前容器的元素個數,如果大于等于閾值(知道這個閾字怎么念嗎?不念 fa 值,
念 yu 值四聲)---即當前數組的長度乘以加載因子的值的時候,就要自動擴容啦。
擴容( resize )就是重新計算容量,向 HashMap 對象里不停的添加元素,而 HashMap 對象內部的數組無法裝載更
多的元素時,對象就需要擴大數組的長度,以便能裝入更多的元素。當然 Java 里的數組是無法自動擴容的,方法
是使用一個新的數組代替已有的容量小的數組,就像我們用一個小桶裝水,如果想裝更多的水,就得換大水桶。
cap =3, hashMap 的容量為4; cap =4, hashMap 的容量為4; HashMap hashMap=new HashMap(cap);
cap =5, hashMap 的容量為8; cap =9, hashMap 的容量為16;
如果 cap 是2的n次方,則容量為 cap ,否則為大于 cap 的第一個2的n次方的數。
HashMap 1.7 與 1.8 的 區別,說明 1.8 做了哪些優化,如何優化的?
HashMap結構圖
在 JDK1.7 及之前的版本中, HashMap 又叫散列鏈表:基于一個數組以及多個鏈表的實現,hash值沖突的時候,
就將對應節點以鏈表的形式存儲。
JDK1.8 中,當同一個hash值( Table 上元素)的鏈表節點數不小于8時,將不再以單鏈表的形式存儲了,會被
調整成一顆紅黑樹。這就是 JDK7 與 JDK8 中 HashMap 實現的最大區別。
其下基于 JDK1.7.0_80 與 JDK1.8.0_66 做的分析
JDK1.7中
使用一個 Entry 數組來存儲數據,用key的 hashcode 取模來決定key會被放到數組里的位置,如果 hashcode 相
同,或者 hashcode 取模后的結果相同( hash collision ),那么這些 key 會被定位到 Entry 數組的同一個
格子里,這些 key 會形成一個鏈表。
在 hashcode 特別差的情況下,比方說所有key的 hashcode 都相同,這個鏈表可能會很長,那么 put/get 操作
都可能需要遍歷這個鏈表,也就是說時間復雜度在最差情況下會退化到 O(n)
JDK1.8中
使用一個 Node 數組來存儲數據,但這個 Node 可能是鏈表結構,也可能是紅黑樹結構
如果插入的 key 的 hashcode 相同,那么這些key也會被定位到 Node 數組的同一個格子里。
如果同一個格子里的key不超過8個,使用鏈表結構存儲。
如果超過了8個,那么會調用 treeifyBin 函數,將鏈表轉換為紅黑樹。
那么即使 hashcode 完全相同,由于紅黑樹的特點,查找某個特定元素,也只需要O(log n)的開銷
也就是說put/get的操作的時間復雜度最差只有 O(log n)
聽起來挺不錯,但是真正想要利用 JDK1.8 的好處,有一個限制:
key的對象,必須正確的實現了 Compare 接口
如果沒有實現 Compare 接口,或者實現得不正確(比方說所有 Compare 方法都返回0) 那 JDK1.8 的 HashMap 其實還是慢于 JDK1.7 的
簡單的測試數據如下:
向 HashMap 中 put/get 1w 條 hashcode 相同的對象
JDK1.7: put 0.26s , get 0.55s JDK1.8 (未實現 Compare 接口): put 0.92s , get 2.1s
但是如果正確的實現了 Compare 接口,那么 JDK1.8 中的 HashMap 的性能有巨大提升,這次 put/get 100W條 hashcode 相同的對象
JDK1.8 (正確實現 Compare 接口,): put/get 大概開銷都在320 ms 左右
final finally finalize
final可以修飾類、變量、方法,修飾類表示該類不能被繼承、修飾方法表示該方法不能被重寫、修飾變量表
示該變量是一個常量不能被重新賦值。
finally一般作用在try-catch代碼塊中,在處理異常的時候,通常我們將一定要執行的代碼方法finally代碼塊
中,表示不管是否出現異常,該代碼塊都會執行,一般用來存放一些關閉資源的代碼。
finalize是一個方法,屬于Object類的一個方法,而Object類是所有類的父類,該方法一般由垃圾回收器來調
用,當我們調用 System.gc() 方法的時候,由垃圾回收器調用finalize(),回收垃圾,一個對象是否可回收的
最后判斷。
對象的四種引用
強引用 只要引用存在,垃圾回收器永遠不會回收
Object obj = new Object(); User user=new User();
可直接通過obj取得對應的對象 如 obj.equels(new Object()); 而這樣 obj 對象對后面 new Object 的一個強
引用,只有當 obj 這個引用被釋放之后,對象才會被釋放掉,這也是我們經常所用到的編碼形式。


 
 
------分隔線----------------------------
鋒哥公眾號


鋒哥微信


關注公眾號
【Java資料站】
回復 666
獲取 
66套java
從菜雞到大神
項目實戰課程
体育彩票开奖时间