阿里《JAVA實習生入職測試題—2019最新》之答案詳解(連載一)


力爭清晰完整准確

1、String類為什么是final的

首先分析String的源碼:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[];
  • 類被final關鍵字限定,說明它不可以被繼承,沒有子類。即持有一個String對象的引用,它必然是String類,而不會是其他的類。
  • value[]是用來存儲值的,被final關鍵字修飾,說明這個數組不可被其它數組替換—即數組的地址不可變更,但是數組的每個元素的值可以變更

private 限定符,保證String字符串數組的值不可在類外被修改。由於未對外暴露可修改的接口,所以String的值一旦被創建,即不可被修改。

  • 線程安全

因為字符串是不可修改的(只能讀不能寫),多個線程可以共享同一個字符串實例

  • 字符串常量池可以大大提高時空間效率

      字符串常量池,詳情請移步    https://segmentfault.com/a/1190000009888357

2、JDK8的HashMap的源碼,實現原理,底層結構

  HashMap的Hash沖突解決,后面單獨會寫一篇博客。

  ConcurrentHashMap的鎖分段,大廠很喜歡問(最近華為電話面試問過我),簡單說一句,就是hashMap的數據是一個數組,用多個鎖來鎖,一個鎖鎖一個節點的數據鏈。

不像以前一個鎖鎖住整個數組,多個線程可分段訪問這些數據,自然效率就高了

  • 首先看Node的源碼
    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; }

   HashMap用 transient Node<K,V>[] table 存值,本質上是鏈表數組(哈希數組+鏈表+紅黑樹),是Hash散列的,即數組非緊密排列,有空隙,詳見下圖

HashMap結構

                              圖01

為什么有紅黑樹,看put(新增)的源碼片段,如下:

  else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);

TreeNode定義的源碼片段,如下:

    static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
        TreeNode<K,V> parent;  // red-black tree links
        TreeNode<K,V> left; TreeNode<K,V> right; TreeNode<K,V> prev; // needed to unlink next upon deletion boolean red; TreeNode(int hash, K key, V val, Node<K,V> next) { super(hash, key, val, next); }

 

  • 容量及動態擴容
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

默認容量-16。resize時,newCap = oldCap << 1( 2進制,左移1位,即*2,舊的容量翻倍,容量可能不是2的冪,視就又容量情況而定)

  • 新增元素
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true); }

    1)如果以前這個key有值,put 操作會用新值替換舊值。

    2)Hash沖突怎么解決

 hash(散列),就是key和存儲位置有個映射關系f,我們稱之為hash函數。hash沖突,就是不同的key,根據hash函數算出來的存儲位置相同,后面添加的元素就和原來的hashCode沖突了,所以要重新按照一定規則計算新的存儲位置。普通HashMap(java 8的HashMap結構如“圖1”,有紅黑樹)結構如下圖:

java8 中的HashMap為了提高查找效率,當鏈表沖突過高,大於閾值時,會將鏈表節點轉化成紅黑樹節點

  • 裝載因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;

load factor默認0.75 ,這個和概率統計有關(Hash沖突概率最低),詳見 http://en.wikipedia.org/wiki/Poisson_distribution

為了減少沖突,當hashMap的數組長度 >  臨界值 就會觸發擴容,所有元素rehash(重新計算hashCode和存儲位置)再放到擴容后的容器中,因為涉及到計算、數據查找、內存拷貝、移動等操作,非常耗時。

臨界值 = current capacity * current load factor。默認臨界值 = DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR = 16 x 0.75 = 12時,就會觸發擴容操作。

 

*****************************************************************************************************

精力有限,想法太多,專注做好一件事就行

  • 我只是一個程序猿。5年內把代碼寫好,技術博客字字推敲,堅持零拷貝和原創
  • 寫博客的意義在於鍛煉邏輯條理性,加深對知識的系統性理解,鍛煉文筆,如果恰好又對別人有點幫助,那真是一件令人開心的事

*****************************************************************************************************


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM