在 Java 中將漢字轉換為漢語拼音,最輕量且成熟的方案是使用 **pinyin4j** 庫。本文針對該庫的核心類 `PinyinHelper`、`HanyuPinyinOutputFormat` 進行詳細講解,並提供一個可直接用於生產的簡易封裝類,支援 **多音字首個讀音**、**自定義分隔符**、**大小寫/聲調/ü 處理** 等常見需求。
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.0</version>
</dependency>
控制拼音輸出風格的三大維度:
| 屬性 | Setter | 枚舉選項 | 示例 (字: 重) |
|---|---|---|---|
| 大小寫 | setCaseType() | LOWERCASE / UPPERCASE | zhong / 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
庫不直接支援字串轉換,需自行迭代字符並組合。兩種常見策略:
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();
}
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();
}
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 雖小而美,掌握 `HanyuPinyinOutputFormat` 三大維度配置與 `PinyinHelper.toHanyuPinyinStringArray` 核心方法,配合簡易封裝,即可滿足 90% 以上的漢字轉拼音業務場景 (搜尋聯想、排序、Slug 生成、首字母縮寫)。對於強多音字消歧需求,請引入 HanLP 等 NLP 級方案。