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

Java 實現漢字轉拼音:pinyin4j 核心 API 詳解與簡易封裝範例

     編輯:Java 相關知識

前言

在 Java 中將漢字轉換為漢語拼音,最輕量且成熟的方案是使用 **pinyin4j** 庫。本文針對該庫的核心類 `PinyinHelper`、`HanyuPinyinOutputFormat` 進行詳細講解,並提供一個可直接用於生產的簡易封裝類,支援 **多音字首個讀音**、**自定義分隔符**、**大小寫/聲調/ü 處理** 等常見需求。

一、Maven 依賴

<dependency>
    <groupId>com.belerweb</groupId>
    <artifactId>pinyin4j</artifactId>
    <version>2.5.0</version>
</dependency>

二、核心類與輸出格式配置

HanyuPinyinOutputFormat

控制拼音輸出風格的三大維度:

屬性Setter枚舉選項示例 (字: 重)
大小寫setCaseType()LOWERCASE / UPPERCASEzhong / ZHONG
聲調setToneType()WITH_TONE_NUMBER (1-4)
WITH_TONE_MARK (ā á ǎ à)
WITHOUT_TONE
zhong4 / zhòng / zhong
ü 處理setVCharType()WITH_V (v)
WITH_U_UNICODE (ü)
WITH_U_AND_COLON (u:)
lv / lü / lu:
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); // 無聲調,適合檢索
format.setVCharType(HanyuPinyinVCharType.WITH_V);     // ü → v

三、核心轉換方法


// 單字轉換:返回 String[],多音字對應多個元素
String[] pinyins = PinyinHelper.toHanyuPinyinStringArray('重', format);
// 結果: ["zhong", "chong"]

// 非漢字字符 (字母、數字、標點) 返回 null
String[] notChinese = PinyinHelper.toHanyuPinyinStringArray('A', format); // null

四、字串級轉換邏輯 (逐字迭代組合)

庫不直接支援字串轉換,需自行迭代字符並組合。兩種常見策略:

策略 1:取首個讀音拼接 (適合排序、Slug、檢索)

public static String toPinyinFirst(String input, String separator) {
    if (input == null || input.isEmpty()) return "";
    StringBuilder sb = new StringBuilder();
    for (char c : input.toCharArray()) {
        String[] arr = PinyinHelper.toHanyuPinyinStringArray(c, format);
        if (arr != null && arr.length > 0) {
            sb.append(arr[0]);
        } else if (Character.isLetterOrDigit(c)) {
            sb.append(Character.toLowerCase(c)); // 保留字母數字
        }
        // 非字母數字漢字 (標點) 可選擇忽略或保留
        if (separator != null) sb.append(separator);
    }
    if (separator != null && sb.length() > separator.length()) {
        sb.setLength(sb.length() - separator.length()); // 移除尾部分隔符
    }
    return sb.toString();
}

策略 2:首字母提取 (適合輸入聯想、縮寫)

public static String toFirstLetters(String input) {
    if (input == null || input.isEmpty()) return "";
    StringBuilder sb = new StringBuilder();
    for (char c : input.toCharArray()) {
        String[] arr = PinyinHelper.toHanyuPinyinStringArray(c, format);
        if (arr != null && arr.length > 0) {
            sb.append(arr[0].charAt(0)); // 取首字母
        } else if (Character.isLetter(c)) {
            sb.append(Character.toLowerCase(c));
        }
    }
    return sb.toString();
}

五、完整封裝工具類 ChineseToPinyinUtil

public class ChineseToPinyinUtil {
    private static final HanyuPinyinOutputFormat DEFAULT_FORMAT;
    static {
        DEFAULT_FORMAT = new HanyuPinyinOutputFormat();
        DEFAULT_FORMAT.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        DEFAULT_FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        DEFAULT_FORMAT.setVCharType(HanyuPinyinVCharType.WITH_V);
    }

    /** 漢字轉拼音 (首個讀音),可指定分隔符,null 表示無分隔 */
    public static String toPinyin(String chinese, String separator) {
        return toPinyin(chinese, separator, DEFAULT_FORMAT);
    }

    /** 完整版:自定義輸出格式 */
    public static String toPinyin(String chinese, String separator, HanyuPinyinOutputFormat format) {
        if (chinese == null || chinese.isEmpty()) return "";
        StringBuilder sb = new StringBuilder();
        for (char c : chinese.toCharArray()) {
            try {
                String[] arr = PinyinHelper.toHanyuPinyinStringArray(c, format);
                if (arr != null && arr.length > 0) {
                    sb.append(arr[0]);
                } else if (Character.isLetterOrDigit(c)) {
                    sb.append(Character.toLowerCase(c));
                }
                // 其他字符 (標點、空格) 默認忽略,如需保留可 sb.append(c)
                if (separator != null) sb.append(separator);
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                // 格式組合非法,回退默認
                sb.append(c);
            }
        }
        if (separator != null && sb.length() > separator.length()) {
            sb.setLength(sb.length() - separator.length());
        }
        return sb.toString();
    }

    /** 獲取拼音首字母字串 */
    public static String toFirstLetters(String chinese) {
        if (chinese == null || chinese.isEmpty()) return "";
        StringBuilder sb = new StringBuilder();
        for (char c : chinese.toCharArray()) {
            try {
                String[] arr = PinyinHelper.toHanyuPinyinStringArray(c, DEFAULT_FORMAT);
                if (arr != null && arr.length > 0) {
                    sb.append(arr[0].charAt(0));
                } else if (Character.isLetter(c)) {
                    sb.append(Character.toLowerCase(c));
                }
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /** 獲取單字所有讀音列表 (多音字完整) */
    public static List getAllPinyin(char c) {
        try {
            String[] arr = PinyinHelper.toHanyuPinyinStringArray(c, DEFAULT_FORMAT);
            return arr != null ? Arrays.asList(arr) : Collections.emptyList();
        } catch (BadHanyuPinyinOutputFormatCombination e) {
            return Collections.emptyList();
        }
    }
}

六、使用範例與輸出

public class Demo {
    public static void main(String[] args) {
        String text = "重慶市ABC";
        System.out.println("首個讀音無分隔: " + ChineseToPinyinUtil.toPinyin(text, null));
        // 輸出: zhongqingshiabc
        System.out.println("首個讀音空格分隔: " + ChineseToPinyinUtil.toPinyin(text, " "));
        // 輸出: zhong qing shi a b c
        System.out.println("首字母: " + ChineseToPinyinUtil.toFirstLetters(text));
        // 輸出: zqsabc
        System.out.println("多音字 '重' 所有讀音: " + ChineseToPinyinUtil.getAllPinyin('重'));
        // 輸出: [zhong, chong]
    }
}

七、注意事項與替代方案

  • 多音字消歧:pinyin4j **無上下文感知能力**,無法自動判斷「長/zhǎng/寬」還是「長/cháng/長度」。如需精準消歧,請使用 **HanLP** (含感知機/CRF/Transformer 模型)。
  • 生僻字/擴展區:pinyin4j 基於 Unicode 基本多文種平面 (BMP),對生僻字 (如 𠮷 U+20BB7) 支援有限。ICU4J `Transliterator` 覆蓋更全。
  • 效能:純 Java 實現,單次轉換微秒級,高併發下無鎖,可直接作為工具方法調用。
  • 維護狀態:pinyin4j 最後更新 2011 年,若專案需長期維護,建議封裝介面以便未來替換實現 (HanLP/ICU4J)。

八、結語

pinyin4j 雖小而美,掌握 `HanyuPinyinOutputFormat` 三大維度配置與 `PinyinHelper.toHanyuPinyinStringArray` 核心方法,配合簡易封裝,即可滿足 90% 以上的漢字轉拼音業務場景 (搜尋聯想、排序、Slug 生成、首字母縮寫)。對於強多音字消歧需求,請引入 HanLP 等 NLP 級方案。

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