工具类之 PinyinUtils(无依赖第三方)

4,930 阅读4分钟

前言:年底了,最近都比较忙,每天能抽出的时间也有点少,而且,现在都在努力解决之前的bug,由于github上有同志提出来了拼音工具类有部分汉字识别出错,这不,趁这两天借鉴了其他的实现方式,立马开车撸码,因为大部分是用在跟姓氏相关,所以对姓氏做了多音字,普通的拼音识别并没有多音字识别哦,如需实现,那就依赖第三方开源库--pinyin4j吧,紧接着,那就发车咯。

上车须知

首先先看下单元测试吧,看是否入老司机们的法眼。

澹台: tantai
尉迟: yuchi
万俟: moqi
单于: chanyu
乐 正确: yue    首字母: y      错误: le    
乘 正确: sheng  首字母: s      错误: cheng 
乜 正确: nie    首字母: n      错误: mie   
仇 正确: qiu    首字母: q      错误: chou  
会 正确: gui    首字母: g      错误: hui   
便 正确: pian   首字母: p      错误: bian  
区 正确: ou     首字母: o      错误: qu    
单 正确: shan   首字母: s      错误: dan   
参 正确: shen   首字母: s      错误: can   
句 正确: gou    首字母: g      错误: ju    
召 正确: shao   首字母: s      错误: zhao  
员 正确: yun    首字母: y      错误: yuan  
宓 正确: fu     首字母: f      错误: mi    
弗 正确: fei    首字母: f      错误: fu    
折 正确: she    首字母: s      错误: zhe   
曾 正确: zeng   首字母: z      错误: ceng  
朴 正确: piao   首字母: p      错误: po    
查 正确: zha    首字母: z      错误: cha   
洗 正确: xian   首字母: x      错误: xi    
盖 正确: ge     首字母: g      错误: gai   
祭 正确: zhai   首字母: z      错误: ji    
种 正确: chong  首字母: c      错误: zhong 
秘 正确: bi     首字母: b      错误: mi    
繁 正确: po     首字母: p      错误: fan   
缪 正确: miao   首字母: m      错误: mou   
能 正确: nai    首字母: n      错误: neng  
蕃 正确: pi     首字母: p      错误: fan   
覃 正确: qin    首字母: q      错误: tan   
解 正确: xie    首字母: x      错误: jie   
谌 正确: shan   首字母: s      错误: chen  
适 正确: kuo    首字母: k      错误: shi   
都 正确: du     首字母: d      错误: dou   
阿 正确: e      首字母: e      错误: a     
难 正确: ning   首字母: n      错误: nan   
黑 正确: he     首字母: h      错误: hei   
用时: 14ms
單元測試: d,y,c,s,
单: d
元: y
測: c
試: s
已初始化的汉字转拼音用时测试: yi chu shi hua de han zi zhuan pin yin yong shi ce shi 
用时: 0ms

站点

  • 拼音相关→PinyinUtils.javaTest
    ccs2Pinyin           : 汉字转拼音
    ccs2Pinyin           : 汉字转拼音
    getPinyinFirstLetter : 获取第一个汉字首字母
    getPinyinFirstLetters: 获取所有汉字的首字母
    getSurnamePinyin     : 根据名字获取姓氏的拼音
    getSurnameFirstLetter: 根据名字获取姓氏的首字母

具体路线

import android.support.v4.util.SimpleArrayMap;

/**
 * 
 *     author: Blankj
 *     blog  : http://blankj.com
 *     time  : 16/11/16
 *     desc  : 拼音相关工具类
 * 
 */
public class PinyinUtils {

    private PinyinUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * 汉字转拼音
     *
     * @param ccs 汉字字符串(Chinese characters)
     * @return 拼音
     */
    public static String ccs2Pinyin(CharSequence ccs) {
        return ccs2Pinyin(ccs, "");
    }

    /**
     * 汉字转拼音
     *
     * @param ccs   汉字字符串(Chinese characters)
     * @param split 汉字拼音之间的分隔符
     * @return 拼音
     */
    public static String ccs2Pinyin(CharSequence ccs, CharSequence split) {
        if (ccs == null || ccs.length() == 0) return null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0, len = ccs.length(); i < len; i++) {
            char ch = ccs.charAt(i);
            if (ch >= 0x4E00 && ch <= 0x9FA5) {
                int sp = (ch - 0x4E00) * 6;
                sb.append(pinyinTable.substring(sp, sp + 6).trim());
            } else {
                sb.append(ch);
            }
            sb.append(split);
        }
        return sb.toString();
    }

    /**
     * 获取第一个汉字首字母
     *
     * @param ccs 汉字字符串(Chinese characters)
     * @return 拼音
     */
    public static String getPinyinFirstLetter(CharSequence ccs) {
        if (ccs == null || ccs.length() == 0) return null;
        return ccs2Pinyin(String.valueOf(ccs.charAt(0))).substring(0, 1);
    }

    /**
     * 获取所有汉字的首字母
     *
     * @param ccs 汉字字符串(Chinese characters)
     * @return 所有汉字的首字母
     */
    public static String getPinyinFirstLetters(CharSequence ccs) {
        return getPinyinFirstLetters(ccs, "");
    }

    /**
     * 获取所有汉字的首字母
     *
     * @param ccs   汉字字符串(Chinese characters)
     * @param split 首字母之间的分隔符
     * @return 所有汉字的首字母
     */
    public static String getPinyinFirstLetters(CharSequence ccs, CharSequence split) {
        if (ccs == null || ccs.length() == 0) return null;
        int len = ccs.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            sb.append(ccs2Pinyin(String.valueOf(ccs.charAt(i))).substring(0, 1)).append(split);
        }
        return sb.toString();
    }

    /**
     * 根据名字获取姓氏的拼音
     *
     * @param name 名字
     * @return 姓氏的拼音
     */
    public static String getSurnamePinyin(CharSequence name) {
        if (name == null || name.length() == 0) return null;
        if (name.length() >= 2) {
            CharSequence str = name.subSequence(0, 2);
            if (str.equals("澹台")) return "tantai";
            else if (str.equals("尉迟")) return "yuchi";
            else if (str.equals("万俟")) return "moqi";
            else if (str.equals("单于")) return "chanyu";
        }
        char ch = name.charAt(0);
        if (surnames.containsKey(ch)) {
            return surnames.get(ch);
        }
        if (ch >= 0x4E00 && ch <= 0x9FA5) {
            int sp = (ch - 0x4E00) * 6;
            return pinyinTable.substring(sp, sp + 6).trim();
        } else {
            return String.valueOf(ch);
        }
    }

    /**
     * 根据名字获取姓氏的首字母
     *
     * @param name 名字
     * @return 姓氏的首字母
     */
    public static String getSurnameFirstLetter(CharSequence name) {
        String surname = getSurnamePinyin(name);
        if (surname == null || surname.length() == 0) return null;
        return String.valueOf(surname.charAt(0));
    }

    // 多音字姓氏映射表
    private static final SimpleArrayMap surnames;

    /**
     * 获取拼音对照表,对比过pinyin4j和其他方式,这样查表设计的好处就是读取快
     * 

当该类加载后会一直占有123KB的内存

*

如果你想存进文件,然后读取操作的话也是可以,但速度肯定没有这样空间换时间快,毕竟现在设备内存都很大

*

如需更多用法可以用pinyin4j开源库

*/ private static final String pinyinTable; static { surnames = new SimpleArrayMap<>(35); surnames.put('乐', "yue"); surnames.put('乘', "sheng"); surnames.put('乜', "nie"); surnames.put('仇', "qiu"); surnames.put('会', "gui"); surnames.put('便', "pian"); surnames.put('区', "ou"); surnames.put('单', "shan"); surnames.put('参', "shen"); surnames.put('句', "gou"); surnames.put('召', "shao"); surnames.put('员', "yun"); surnames.put('宓', "fu"); surnames.put('弗', "fei"); surnames.put('折', "she"); surnames.put('曾', "zeng"); surnames.put('朴', "piao"); surnames.put('查', "zha"); surnames.put('洗', "xian"); surnames.put('盖', "ge"); surnames.put('祭', "zhai"); surnames.put('种', "chong"); surnames.put('秘', "bi"); surnames.put('繁', "po"); surnames.put('缪', "miao"); surnames.put('能', "nai"); surnames.put('蕃', "pi"); surnames.put('覃', "qin"); surnames.put('解', "xie"); surnames.put('谌', "shan"); surnames.put('适', "kuo"); surnames.put('都', "du"); surnames.put('阿', "e"); surnames.put('难', "ning"); surnames.put('黑', "he"); pinyinTable = new StringBuilder(125412).toString();//由于表太长,请参看源码 } }

终点站

为了实现姓氏多音字,我也是大费周折地找了很多,如果你们觉得有所不足或错误,那么欢迎留言,好了,终点站到了,如果对本次旅途满意的话,请给五星好评哦,毕竟老司机这次真的牺牲了很多时间才换来这么一份工具类,如果该工具类依赖其他工具类,都可以在我的Android开发人员不得不收集的代码(持续更新中)中找到。