Java坑

1.集合


Collection

Map

紅色的表示接口,黑色的表示實現類。

  • ArrayList 、 LinkedList 、 Vector 的底層實現和區別
    ArrayList:

  • Java集合干貨系列-(一)ArrayList源碼解析

    jdk>=7: int newCapacity = oldCapacity + (oldCapacity >> 1); jdk<7: int newCapacity = (oldCapacity * 3)/2 + 1; android: int newSize=oldSize+newPartSize

    System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element;

    • elementData的容量默認是10,android中是12
    • 提前預知性的設置一個大容量,可減少擴容的次數,從而提高性能
    • 容量不足時,再添加原來的一半大小(JDK=8)
    • Android擴容:newSize=oldSize+newPartSize ToRead:ArrayList 擴容 Android Java 真的不一樣
    • ArrayList的克隆函數,即是將全部元素克隆到一個數組中
    • insert的index越小,需要復制的數據越多。
    • indexOf(Object o)從小到大遍歷,match則返回索引,否則返回-1
    • ArrayList實現java.io.Serializable的方式。當寫入到輸出流時,先寫入“容量”,再依次寫入“每一個元素”;當讀出輸入流時,先讀取“容量”,再依次讀取“每一個元素”
    • 舉個例子
      oldSzie=20 addAll(newPart) newPartSize=50;
      JDK 中 old+old>>1=35 35<70 newSize=70 ---> Size=70
      Android中
      20+50 ---->70 70-1=69>6--->69+34=103 size=103
    • Vector每次擴容請求其大小的2倍空間,而ArrayList是1.5倍
      LinkedList
  • Java集合干貨系列-(二)LinkedList源碼解析

    • Entry是雙向鏈表節點所對應的數據結構
    • LinkedList 實現 Deque 接口,即能將LinkedList當作雙端隊列使用,且是基于雙向循環鏈表實現的
    • LinkedList的查找是通過二分(簡單的一次二分),所以index所對應的元素越靠近中間所費時間越長
    • Deque的操作

    boolean add(E e); // 插入隊尾,要么返回true,要么拋出異常
    boolean offer(E e);//插入隊尾,插入成功true,插入失敗false,其它拋出異常

    E remove(); //移除隊頭元素,并返回,空隊列拋出異常
    E poll(); //移除隊頭元素,并返回,空隊列返回null

    E element(); //獲取但不移除隊列頭的元素,空隊列拋出異常
    E peek(); //獲取但不移除隊列頭的元素,空隊列返回null

    removeFirstOccurrence(Object):從此雙端隊列移除第一次出現的指定元素
    removeLastOccurrence(Object):從此雙端隊列移除最后一次出現的指定元素


  • HashMap 和 HashTable 的底層實現和區別,兩者和 ConcurrentHashMap 的區別。

|HashTable|HashMap|
| -----|:----:| ----:|
|線程安全|非線程安全|
|不允許null|允許null(key只允許一個取null)|
|效率低|效率高|
|sychronized|無sychronized|
|11,old*2+1|16,空間左移1位至不小于實際需要的長度|

HashMap:

  • Java集合干貨系列-(三)HashMap源碼解析
    • 默認初始容量 (16) 、默認加載因子 (0.75)
    • modCount是用來實現fail-fast機制的(fail-fast:在使用迭代器的過程中有其他線程修改了map,會拋出ConcurrentModificationException——modCount到底是干什么的呢
    • threshold是HashMap的閾值,用于判斷是否需要調整HashMap的容量。threshold的值="容量*加載因子",當HashMap中存儲數據的數量達到threshold時,就需要將HashMap的容量加倍。
    • 擴容的時候將對每個元素全部重新計算index,而不是簡單的把原table對應index位置元素簡單的移動到新table對應位置
    • HashMap線程安全化:
Map hashMap = new HashMap();
hashMap = Collections.synchronizedMap(hashMap);
Collections.synchronizedXXX:
對hashMap的操作全部重新封裝,幫我們在操作HashMap時自動添加了synchronized來實現線程同步
  • Hashtable計算hash是直接使用key的hashcode對table數組的長度直接進行取模
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
  • HashMap計算hash對key的hashcode進行了二次hash,以獲得更好的散列值,然后對table數組長度取摸
static int hash(int h) {
     // This function ensures that hashCodes that differ only by
     // constant multiples at each bit position have a bounded
     // number of collisions (approximately 8 at default load factor).
     h ^= (h >>> 20) ^ (h >>> 12);
     return h ^ (h >>> 7) ^ (h >>> 4);
 }

static int indexFor(int h, int length) {
     return h & (length-1);
 }

ConcurrentHashMap


jdk<= 7 : ConcurrentHashMap 的結構示意圖
  • Segment的個數是大于等于concurrencyLevel的第一個2的n次方的數

  • ConcurrentHashMap是基于lock操作,lock鎖住的不是對象整體。
    要填的坑:jdk=8:基于CAS算法 (樂觀鎖的應用)

  • ConcurrentHashMap基于concurrentLevel劃分出多個Segment來對key-value進行存儲,從而避免每次鎖定整個數組,在默認的情況下,允許16個線程并發無阻塞的操作集合對象,盡可能地減少并發是的阻塞現象。

  • 深度剖析ConcurrentHashMap(JDK7版本)

  • ConcurrentHashMap源碼分析(JDK8版本)

悲觀鎖

lock();
some operation;
unlock();

樂觀鎖

do{
expected = resource;//獲取一次預期值
some operation;          
}while(resource == expected && 進行resource訪問);
//while條件=如果實際值和預期值一樣說明這期間沒有其他人訪問,則可以對資源進行修改

樂觀鎖與悲觀鎖及應用舉例
樂觀鎖和悲觀鎖


  • HashMap 的 hashcode 的作用?什么時候需要重寫?如何解決哈希沖突?查找的時候流程是如何?
    • hashcode是用來查找的
    • 當equals方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規協定,該協定聲明相等對象必須具有相等的哈希碼。(想想,你要在一個桶里找東西,你必須先要找到這個桶啊,你不通過重寫hashcode()來找到桶,光重寫equals()有什么用啊 )

Arraylist 和 HashMap 如何擴容?負載因子有什么作用?如何保證讀寫進程安全?


TreeMap 、 HashMap 、 LinkedHashMap 的底層實現區別。
Collection 包結構的組成, Map 、 Set 等內部接口的特點與用法。

**2 ** **并發 **( Executor 框架和多線程基礎):
Thread 與 Runable 如何實現多線程
線程同步的方法有什么;鎖, synchronized 塊,信號量等
鎖的等級:方法鎖、對象鎖、類鎖
生產者消費者模式的幾種實現,阻塞隊列實現, sync 關鍵字實現, lock 實現等
ThreadLocal 的設計理念與作用, ThreadPool 用法與優勢(這里在 Android SDK 原生的 AsyncTask 底層也有使用)
線程池的底層實現和工作原理(建議寫一個雛形簡版源碼實現)
幾個重要的線程 api , interrupt , wait , sleep , stop 等等

**3 ** ** IO **( IO,NIO ,目前 okio 已經被集成 Android 包)
IO 框架主要用到什么設計模式
NIO 包有哪些結構?分別起到的作用?
NIO 針對什么情景會比 IO 有更好的優化?
OKIO 底層實現

**4 ** **其他的 java ****語言特性 **:
反射機制
String 類內部實現,能否改變 String 對象內容,比較經典的 String 字面量筆試題
Object 有哪些公用方法?
try catch 塊, try 里有 return , finally 也有 return ,如何執行這類型的筆試題
Exception 與 Error 的區別
泛型的優缺點
另外就是關注最新版本 jdk 的新特性,例如 Lambda 表達式

**5 ** JVM
自動內存管理機制, GC 算法,運行時數據區結構,可達性分析工作原理,如何分配對象內存
類加載機制,反射機制,雙親委派機制,類加載器的種類
Jvm 內存模型,先行發生原則, violate 關鍵字作用


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Java SE 基礎: 封裝、繼承、多態 封裝: 概念:就是把對象的屬性和操作(或服務)結合為一個獨立的整體,并盡...
    Jayden_Cao閱讀 2,140評論 0 8
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,518評論 0 3
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,366評論 11 349
  • 一、基本數據類型 注釋 單行注釋:// 區域注釋:/* */ 文檔注釋:/** */ 數值 對于byte類型而言...
    龍貓小爺閱讀 4,288評論 0 16
  • 忙碌的一天,就這樣,像往常一樣,結束,伴著電腦屏幕由藍色變為黑色,上班時候的那種神經緊繃也放松下來,那一刻...
    ViviGo_M閱讀 291評論 0 0