在使用者搜尋、通訊錄排序、拼音輸入提示、URL Slug 生成等場景,將漢字轉換為拼音或首字母是剛需。pinyin4j 是 Java 生態最成熟、輕量的拼音轉換庫 (最後版本 2.5.0,2011 年),雖久未更新但穩定可靠。本文詳細講解 Maven 整合、核心 API、輸出格式控制、多音字處理、首字母提取與封裝工具類最佳實踐。
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.0</version>
</dependency>
或手動下載 pinyin4j-2.5.0.jar 放入 Classpath。
控制拼音輸出風格:
| 屬性 | 枚舉值 | 說明 |
|---|---|---|
| 大小寫 | LOWERCASE / UPPERCASE | 小寫 / 大寫 |
| 聲調 | WITH_TONE_NUMBER (1-4) WITH_TONE_MARK (ā á ǎ à) WITHOUT_TONE | 數字標調 / 符號標調 / 無聲調 |
| ü 處理 | WITH_V (v) WITH_U_UNICODE (ü) WITH_U_AND_COLON (u:) | 用 v / ü / u: 表示 |
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]
// 字串轉換:需逐字迭代組合
String input = "重慶";
List result = new ArrayList<>(List.of(""));
for (char c : input.toCharArray()) {
String[] arr = PinyinHelper.toHanyuPinyinStringArray(c, format);
List next = new ArrayList<>();
for (String prefix : result) {
if (arr == null) { // 非漢字 (字母/數字/符號) 保留原樣
next.add(prefix + c);
} else {
for (String py : arr) next.add(prefix + py);
}
}
result = next;
}
// result: [zhongqing, chongqing] (多音字笛卡爾積)
public class PinYinUtil {
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);
}
/** 獲取字串完整拼音列表 (多音字全排列) */
public static List getFullPinyinList(String str) {
if (str == null || str.isEmpty()) return Collections.emptyList();
List result = new ArrayList<>(List.of(""));
for (char c : str.toCharArray()) {
String[] pys = PinyinHelper.toHanyuPinyinStringArray(c, DEFAULT_FORMAT);
List next = new ArrayList<>();
for (String prefix : result) {
if (pys == null) { // 非漢字直接拼接
next.add(prefix + c);
} else {
for (String py : pys) next.add(prefix + py);
}
}
result = next;
}
return result;
}
/** 獲取首字母列表 (多音字首字母全排列) */
public static List getFirstLettersList(String str) {
if (str == null || str.isEmpty()) return Collections.emptyList();
List result = new ArrayList<>(List.of(""));
for (char c : str.toCharArray()) {
String[] pys = PinyinHelper.toHanyuPinyinStringArray(c, DEFAULT_FORMAT);
List next = new ArrayList<>();
for (String prefix : result) {
if (pys == null) {
if (Character.isLetter(c)) next.add(prefix + Character.toLowerCase(c));
else next.add(prefix + c); // 保留數字符號
} else {
Set firstChars = new LinkedHashSet<>();
for (String py : pys) firstChars.add(py.charAt(0));
for (char fc : firstChars) next.add(prefix + fc);
}
}
result = next;
}
return result;
}
/** 簡單模式:取第一個讀音拼接 (適合檢索、排序) */
public static String toSimplePinyin(String str, String separator) {
StringBuilder sb = new StringBuilder();
for (char c : str.toCharArray()) {
String[] pys = PinyinHelper.toHanyuPinyinStringArray(c, DEFAULT_FORMAT);
if (pys != null && pys.length > 0) {
sb.append(pys[0]);
} else if (Character.isLetterOrDigit(c)) {
sb.append(Character.toLowerCase(c));
}
if (separator != null && sb.length() > 0) sb.append(separator);
}
if (separator != null && sb.length() > 0) sb.setLength(sb.length() - separator.length());
return sb.toString();
}
/** 簡單首字母 */
public static String toSimpleFirstLetters(String str) {
StringBuilder sb = new StringBuilder();
for (char c : str.toCharArray()) {
String[] pys = PinyinHelper.toHanyuPinyinStringArray(c, DEFAULT_FORMAT);
if (pys != null && pys.length > 0) {
sb.append(pys[0].charAt(0));
} else if (Character.isLetter(c)) {
sb.append(Character.toLowerCase(c));
}
}
return sb.toString();
}
}
| 場景 | 推薦方法 | 理由 |
|---|---|---|
| 使用者搜尋聯想 (輸入 "zq" 匹配 "重慶") | getFirstLettersList() 產生所有首字母組合建立倒排索引 | 覆蓋所有讀音,召回率高 |
| 通訊錄排序 / URL Slug | toSimplePinyin() 取首讀音 | 確定性、可排序、長度可控 |
| 語音合成 / 朗讀 | 需結合分詞 + 多音字消歧模型 (如 HanLP) | pinyin4j 無上下文消歧能力 |
| 身份證/姓名驗證 | 嚴格模式:僅允許單一讀音字,或人工複核 | 避免歧義 |
pinyin4j 雖屬「老牌」庫,但在無需複雜 NLP 依賴、輕量級部署的場景下依然是最佳選擇。合理封裝工具類、根據業務場景選擇全排列或簡單模式、注意多音字組合爆炸風險,即可輕鬆實現漢字轉拼音/首字母功能,顯著提升使用者搜尋與輸入體驗。