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

Java Unicode 代理對編程完全指南:API、效能與最佳實踐

     編輯:Java 相關知識

背景:從 UCS-2 到 UTF-16

早期 Java 用 16 位 char 表示 Unicode(BMP 範圍 0x0000~0xFFFF)。Unicode 3.1 擴展至 0x10FFFF,超出 16 位容量。UTF-16 引入代理對:高代理(0xD800~0xDBFF)+ 低代理(0xDC00~0xDFFF)組合表示補充字符(0x10000~0x10FFFF),共 1,048,576 碼位。Java 1.5 保留 char 相容性,新增碼位(code point,32 位)概念支援 UTF-32。

順序訪問:七種實作與效能比較

將字串轉為 int[] 碼位陣列。測試環境:10,000 代理對 + 10,000 非代理對,重複 10,000 次。

示例方法關鍵 API相對耗時
1-1基準(忽略代理對)charAt1.00x
1-2手動檢測 isSurrogatePairisHighSurrogate, isLowSurrogate, toCodePoint1.38x
1-3標準 APIcodePointCount, codePointAt, offsetByCodePoints2.80x
1-4反向遍歷 codePointBeforecodePointBefore, offsetByCodePoints2.72x
1-5優化:charCountcodePointAt, charCount1.68x
1-6直接存取 char[]toCharArray, Character.codePointAt1.51x
1-7面向物件 CharBufferCharBuffer, IntBuffer, Character.codePointAt(CharSequence)2.15x

推薦實作(範例 1-5/1-6)

// 1-5: 使用 charCount 避免 offsetByCodePoints 開銷
int[] toCodePointArray(String str) {
    int[] acp = new int[str.codePointCount(0, str.length())];
    for (int i = 0, cp; i < str.length(); i += Character.charCount(cp)) {
        cp = str.codePointAt(i);
        acp[j++] = cp;
    }
    return acp;
}

// 1-6: 大量資料時轉 char[] 更快
int[] toCodePointArray(String str) {
    char[] ach = str.toCharArray();
    int[] acp = new int[Character.codePointCount(ach, 0, ach.length)];
    for (int i = 0, cp; i < ach.length; i += Character.charCount(cp)) {
        cp = Character.codePointAt(ach, i);
        acp[j++] = cp;
    }
    return acp;
}

隨機訪問:避免 O(N²) 陷阱

按碼位索引切分字串。關鍵在於避免重複從頭計算 offsetByCodePoints:

// 低效:每次從 0 開始計算
int begin = str.offsetByCodePoints(0, pos);
int end = str.offsetByCodePoints(0, pos + width);

// 高效:從當前 char 位置偏移
int end = str.offsetByCodePoints(pos, width);
pos = end; // 直接更新 char 位置

測試顯示:優化版隨字串長度線性增長,未優化版呈平方級增長。

資訊 API 快速查閱

大多數 Character 方法提供 char 與 int (code point) 雙重載。關鍵差異在於補充字符與高代理的返回值不同(見原文表 2)。

其他實用 API

  • Character.toChars(cp)、String(int[])、StringBuilder.appendCodePoint:碼位轉字串
  • String.indexOf(cp)、StringBuffer.codePointCount:字串操作
  • IllegalFormatCodePointException:格式化異常

建立字串的 5 種方式效能

int cp = 0x20B9F;
new String(new int[]{cp}, 0, 1);        // 206ms
new String(Character.toChars(cp));       // 187ms ✓
String.valueOf(Character.toChars(cp));   // 195ms
new StringBuilder().appendCodePoint(cp).toString(); // 269ms
String.format("%c", cp);                 // 3781ms ✗ (僅用於最終輸出)

結語

Unicode 持續擴展(Emoji、古字符、東亞擴展),正確處理代理對是國際化軟體的必修課。掌握 codePointAt/charCount 組合與 offsetByCodePoints 的正確用法,能在相容性與效能間取得最佳平衡。

處理時間比較圖1 處理時間比較圖2 API 返回值表1 API 返回值表2

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved