pinyin4j项目实战演练

随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666)

在实际项目中,经常会遇到汉字转拼音的需求,比如要根据拼音进行模糊查询,比如安卓里面的联系人就是通过拼音进行搜索的,这个时候就需要把汉字转换为拼音,才能进行拼音的模糊匹配,那么,在今天的文章中,介绍一个非常强大的拼音处理库pinyin4j,相信很多人都听说过甚至使用过,在这里,我总结下它的常见用法,并封装成方法,供以后项目方便调用。

我们知道,汉字是有多音字的,我们先从简单的开始分析,先不考虑多音字的情况。

下面介绍第一个封装的方法,获取汉字的拼音

	/**
	 * 获取拼音,多音字只取一种
	 * 
	 * @param input
	 * @return
	 */
	public static String getSpell(String input) {
		StringBuffer py = new StringBuffer();
		char[] cs = input.trim().toCharArray();
		HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
		// 不带声调
		format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
		// 设置大小写
		format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		// 拼音中的u输出为v,例如lv
		format.setVCharType(HanyuPinyinVCharType.WITH_V);
		for (char c : cs) {
			if (isChinese(c)) {
				try {
					String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(c, format);
					if (pinyin != null && pinyin.length > 0) {
						py.append(pinyin[0]);
					}
				} catch (BadHanyuPinyinOutputFormatCombination e) {
					logger.error("", e);
				}

			} else {
				py.append(c);
			}
		}
		return py.toString();
	}

代码非常简单,核心代码是String[] pinyin=PinyinHelper.toHanyuPinyinStringArray(c, format),这就是将汉字转换为拼音的API,这里返回的是所有拼音,本方法中只取第一个拼音来说明,HanyuPinyinOutputFormat是拼音输出格式类,可以设置大小写,是否带声调等等。测试代码:PinyinUtil.getSpell("我是一个好人"),打印结果为woshiyigehaoren,是不是很简单呢

还有一种常用需求,获取拼音的首字母,这个在项目中也使用非常多,既然拼音都获取到了,首字母只需要取第一个字符就可以了,代码如下:

	public static String getFirstSpell(String input) {
		StringBuffer py = new StringBuffer();
		char[] cs = input.trim().toCharArray();
		HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
		format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
		format.setVCharType(HanyuPinyinVCharType.WITH_V);
		format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
		for (char c : cs) {
			if (isChinese(c)) {
				try {
					String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(c, format);
					if (pinyin != null && pinyin.length > 0) {
						py.append(pinyin[0].charAt(0));
					}
				} catch (BadHanyuPinyinOutputFormatCombination e) {
					logger.error("", e);
				}

			} else {
				py.append(c);
			}
		}
		return py.toString().replaceAll("\\W", "").trim();
	}

只需要对刚才使用toHanyuPinyinStringArray获取的拼音取第一个字母就可以了。测试结果:WSYGHR

那么单音字分析了,我们该考虑多音字了,如果换一串汉字再使用上面获取拼音的方法,就可能不是我们想要的效果了,比如PinyinUtil.getFirstSpell("长沙市长"),结果为zhangshashizhang,第一个字就不是我们想要的拼音了。处理方法如下:

	public static List<String> getPolyphoneSpell(String input) {
		StringBuffer py = new StringBuffer();
		char[] cs = input.toCharArray();
		HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
		format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
		for (char c : cs) {
			if (isChinese(c)) {
				try {
					// 取得当前汉字的所有全拼
					String[] strs = PinyinHelper.toHanyuPinyinStringArray(c, format);
					if (strs != null) {
						for (int j = 0; j < strs.length; j++) {
							py.append(strs[j]);
							if (j != strs.length - 1) {
								py.append(",");
							}
						}
					}
				} catch (BadHanyuPinyinOutputFormatCombination e) {
					logger.error("", e);
				}
			} else {
				py.append(c);
			}
			py.append(" ");
		}
		return combinePinyin(removeRepeat(py.toString()));
	}

这里的处理方式为,将同一个字的多音字用‘,’隔开,不同汉字拼音用空格隔开,得到的效果如下:zhang,chang sha,sha shi zhang,chang,然后进行第二步排重,这里看到了‘沙’字在忽略声调的情况下有两个一样的多音字,排重方法如下:

	private static List<Map<String, Integer>> removeRepeat(String pinyins) {
		// 去除重复拼音后的拼音列表
		List<Map<String, Integer>> l = new ArrayList<>();
		// 用于去重
		Map<String, Integer> only = null;
		String[] all = pinyins.split(" ");
		// 遍历每个汉字的拼音
		for (String str : all) {
			only = new Hashtable<>();
			// 拆分单个汉字的多音字拼音
			String[] pol = str.split(",");
			// 去重处理
			for (String s : pol) {
				Integer count = only.get(s);
				if (count == null) {
					only.put(s, new Integer(1));
				} else {
					only.remove(s);
					count++;
					only.put(s, count);
				}
			}
			l.add(only);
		}
		return l;
	}

思路很简单,用一个map来存储每个汉字的多音字,重复的就只保留一个。接下来进行第三步,拼音整合,将所有可能性组合起来,比如上面的例子,在排重以后,还有两个多音字,就有四种组合,组合代码方法如下:

	private static List<String> combinePinyin(List<Map<String, Integer>> list) {
		// 保存组合数据
		Map<String, Integer> map = null;
		// 遍历每一组集合
		for (int i = 0; i < list.size(); i++) {
			// 这次与上一次组合的临时Map
			Map<String, Integer> temp = new Hashtable<String, Integer>();
			// 第一次循环,取集合第一个数据赋值
			if (map == null) {
				for (String s : list.get(i).keySet()) {
					String str = s;
					temp.put(str, 1);
				}
			} else {
				// 组合上次与这次的拼音
				for (String s : map.keySet()) {
					for (String s1 : list.get(i).keySet()) {
						String str = s + s1;
						temp.put(str, 1);
					}
				}
				// 清理上一次组合数据
				if (temp != null && temp.size() > 0) {
					map.clear();
				}
			}
			// 保存新组合数据
			if (temp != null && temp.size() > 0) {
				map = temp;
			}
		}
		List<String> result = new ArrayList<>();
		if (map != null) {
			for (String str : map.keySet()) {
				result.add(str);
			}
		}
		return result;

	}

思路也非常简单,用一个map来存储整合的数据,每次遍历将新的数据和之前整合的数据再组装,然后作为新的组合数据,遍历完后map就存储所有整合完的多音字情况。代码有非常详细的注释,相信大家都很容易看懂。然后将所有组合添加到集合返回,方便使用。测试结果如下:[zhangshashichang, changshashichang, zhangshashizhang, changshashizhang]

好,到这里获取多音字拼音介绍完了,获取首字母思路就是一样的了,直接上代码:

	public static List<String> getPolyphoneFirstSpell(String input) {
		StringBuffer py = new StringBuffer();
		char[] cs = input.toCharArray();
		HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
		format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
		for (char c : cs) {
			if (isChinese(c)) {
				try {
					// 取得当前汉字的所有全拼
					String[] strs = PinyinHelper.toHanyuPinyinStringArray(c, format);
					if (strs != null) {
						for (int j = 0; j < strs.length; j++) {
							// 取首字母
							py.append(strs[j].charAt(0));
							if (j != strs.length - 1) {
								py.append(",");
							}
						}
					}
				} catch (BadHanyuPinyinOutputFormatCombination e) {
					logger.error("", e);
				}
			} else {
				py.append(c);
			}
			py.append(" ");
		}
		return combinePinyin(removeRepeat(py.toString()));
	}

测试结果:[cssc, zssz, zssc, cssz]

判断是否为汉字的方法:

	public static boolean isChinese(char c) {
		return c >= 0x4E00 && c <= 0x9FA5;
	}

到这里,pinyin4j的基本使用介绍完了,这个库还有其它非常强大的功能,比如支持声调等等,留着大家继续探究吧。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

u010142437

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值