首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java String.equals() 潛在優化:利用 char[] 共享特性加速比較

     編輯:Java 相關知識

背景:String 內部結構

JDK 1.4/1.5 中 String 核心欄位:

private final char value[];  // 字元陣列
private final int offset;    // 起始索引
private final int count;     // 字元長度

建構子 String(String original) 會嘗試共享底層 char[]:若原陣列長度大於實際內容,複製;否則直接引用同一陣列。

現狀:equals() 未利用共享特性

原始 equals(Object anObject) 邏輯:

  1. this == anObject → true
  2. 型別檢查 → 長度比對 → 逐字元迴圈比對

缺口:未檢查 value[] 與 offset 是否完全相同。若兩個 String 共享同一 char[] 且偏移/長度相同,理應直接回傳 true。

提出優化:增加參考相等性快速判斷

public boolean equals(Object anObject) {
    if (this == anObject) return true;
    if (anObject instanceof String) {
        String another = (String) anObject;
        int n = count;
        if (n == another.count) {
            char v1[] = value;
            char v2[] = another.value;
            int i = offset;
            int j = another.offset;
            
            // === 新增:陣列引用與偏移皆同 → 內容必同 ===
            if (i == j && v1 == v2) return true;
            
            while (n-- != 0) {
                if (v1[i++] != v2[j++]) return false;
            }
            return true;
        }
    }
    return false;
}

效益分析

  • 適用場景:substring()、new String(existing)、字面常量池複用等產生共享陣列的情況。
  • 性能增益:將 O(n) 字元比對降為 O(1) 參考比對,對長字串、高頻比對 (如 Map Key、集合去重) 意義顯著。
  • 相容性:純粹優化,不改變語義,符合 equals 合約。

為何 JDK 未採納?(推測)

  1. 共享情境有限:現代 JDK (6+) substring 已改為複製陣列,避免記憶體洩漏,共享機會大減。
  2. 安全性考量:value 為 package-private,子類或同包類可能竄改陣列內容 (雖 String 為 final),引入參考比對需極度確信不可變性。
  3. 常見路徑已優化:this == anObject 涵蓋最常見的同一物件比對;字面常量編譯期已合併。

結語

此優化在早期 JDK 架構下合理且有效,展現了深入理解類別內部實現的價值。現代開發中,若有大量長字串比對需求,可考慮:

  • 使用 intern() 進入常量池,轉為參考比對。
  • 自訂 CharSequence 實現攜帶雜湊碼快速判斷。
  • 或直接接受 O(n) — 現代 CPU 快取下逐字元比對極快。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved