浅析pinyin4j源码 简单利用pinyin4j对中文字符进行自然排序

pinyin4j项目  官网地址 http://pinyin4j.sourceforge.net/

我们先把资源下载下来,连同源码和jar包一起放入工程。如下图:

接下来在demo包下,我们写一个测试类,简单使用pinyin4j对中文字符进行自然排序

新建一个ConvertTest.java

package demo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sourceforge.pinyin4j.PinyinHelper;

public class ConvertTest {

    public static void main(String[] args) {
        String src = "我们中间出了一个叛徒";
        char[] arr = src.toCharArray();
        System.out.println("数组长度是:"+arr.length);
        System.out.print("原始顺序:");
        for (char temp : arr) {
            System.out.print(temp+" ");
        }
        System.out.println();
        convertToHanyuPinyin(arr);
    }

    private static List<String> convertToHanyuPinyin(char[] array){
        HashMap<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < array.length; i++) {
            //得到拼音首字母
            String value = (PinyinHelper.toHanyuPinyinStringArray(array[i]))[0].substring(0, 1);
            map.put(String.valueOf(array[i]), value);
        }
        System.out.println(map);
        List<String> list = sort(map);
        return list;
    }

    private static List<String> sort(Map map){
         List<Map.Entry<String, String>> infoIds =
                         new ArrayList<Map.Entry<String, String>>(map.entrySet());
        // 对HashMap中的 value 进行排序
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1,
                    Map.Entry<String, String> o2) {
                return (o1.getValue()).compareTo(o2.getValue());
            }
        });  

        List<String> list = new ArrayList<String>();
        /*****************FOR TEST***********************/
        List<String> letterList = new ArrayList<String>();
        /*****************FOR TEST***********************/
        // 对HashMap中的 value 进行排序后  显示排序结果
        for (int i = 0; i < infoIds.size(); i++) {
            Map.Entry<String,String> entry = infoIds.get(i);
            list.add(entry.getKey());
            letterList.add(entry.getValue());
        }

        /*****************FOR TEST***********************/
        System.out.print("自然顺序:");
        for (String string : list) {
            System.out.print(string + "   ");
        }

        System.out.println();

        System.out.print("字母顺序:");
        for (String string : letterList) {
            System.out.print(string +" ");
        }
        /*****************FOR TEST***********************/
        return list;
    }
}

输出结果为:

可以看到最终的输出顺序已经是按照自然顺序排序后的结果了。

简单说一下步骤:

1.我们先将字符串序列转换成 单个字符key, 首字母value  的map形式,

如 {个=g, 徒=t, 我=w, 出=c, 叛=p, 了=l, 中=z, 一=y, 间=j, 们=m}。

2. 然后针对map中的value进行排序,并返回排序过后的key值。

(PS:当然这里也可以对key值进行排序,但是最好还是针对value。

因为我们这里截取的是首字母,并不是整个拼音音节。)

代码缺点:

1.只是针对中文字符的第一个拼音进行排序,但是汉语中存在多音字。

2.只是针对字符的首字母进行排序,并不是整个拼音字节,并不严谨,适合粗略排序的场景。

下面简单分析一下,pinyin4j的转换流程。

如上图,其中核心的类就是PinyinHelper。它可以转换许多类型的拼音,这里我们只看汉语拼音,其他的与之类似。

追踪代码 PinyinHelper.toHanyuPinyinStringArray

按ctrl + 鼠标左键。

static public String[] toHanyuPinyinStringArray(char ch)
    {
        return getUnformattedHanyuPinyinStringArray(ch);
    }

继续跟踪代码

private static String[] getUnformattedHanyuPinyinStringArray(char ch)
    {
        return ChineseToPinyinResource.getInstance().getHanyuPinyinStringArray(ch);
    }

调用ChineseToPinyinResource示例的getHanyuPinyinStringArray方法

String[] getHanyuPinyinStringArray(char ch)
    {
        String pinyinRecord = getHanyuPinyinRecordFromChar(ch);

        if (null != pinyinRecord)
        {       //得到左括号( 的索引值
            int indexOfLeftBracket = pinyinRecord.indexOf(Field.LEFT_BRACKET);       //得到右括号) 的索引值
            int indexOfRightBracket = pinyinRecord.lastIndexOf(Field.RIGHT_BRACKET);
            //得到字符对应的拼音
            String stripedString = pinyinRecord.substring(indexOfLeftBracket
                    + Field.LEFT_BRACKET.length(), indexOfRightBracket);
            //以逗号.为分隔 返回String[] 数组
            return stripedString.split(Field.COMMA);

        } else
            return null; // no record found or mal-formatted record
    }

关键的方法getHanyuPinyinRecordFromChar

private String getHanyuPinyinRecordFromChar(char ch)
    {
        int codePointOfChar = ch;
        //转换成unicode对应的字符
        String codepointHexStr = Integer.toHexString(codePointOfChar).toUpperCase();
        //从表中查询字符
        // fetch from hashtable
        String foundRecord = getUnicodeToHanyuPinyinTable().getProperty(codepointHexStr);
        //如果是合法的字符就返回,否则返回null
        return isValidRecord(foundRecord) ? foundRecord : null;
    }

就是如下图的资源:

时间: 2024-10-10 03:00:33

浅析pinyin4j源码 简单利用pinyin4j对中文字符进行自然排序的相关文章

浅析pinyin4j源码 简单利用pinyin4j对中文字符进行自然排序(转)

pinyin4j项目  官网地址 http://pinyin4j.sourceforge.net/ 我们先把资源下载下来,连同源码和jar包一起放入工程.如下图: 接下来在demo包下,我们写一个测试类,简单使用pinyin4j对中文字符进行自然排序 新建一个ConvertTest.java package demo; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; im

【仿乐享微信源码】利用第三方微信营销托管平台快速增加粉丝,形成良好互动,打造精美微信APP

99%的人不知道的微信秘密!微信里的商机.仿乐享微信源码分享,把你的生意做到微信里. WeiKuCMS  (微酷CMS)功能特点:人工客服新功能正式上线!粉丝行为分析.渠道二维码生成.二维码折扣,微菜单,微统计,会员卡签到,微会员,刮刮卡,大转盘,优惠券,积分兑换,微官网,砸金蛋,微调研,微投票,微相册,微商城,微团购,微留言,微喜帖,商家入驻,微门店,微餐饮,微酒店,微教育,微物业,微医疗,微信墙,微花店,微美容,微生活. 微信公共账号轻松接入,无限自定义图文回复.欢迎您的加入! 微酷WeiK

kafka 0.8.1 新producer 源码简单分析

1 背景 最近由于项目需要,需要使用kafka的producer.但是对于c++,kafka官方并没有很好的支持. 在kafka官网上可以找到0.8.x的客户端.可以使用的客户端有C版本客户端,此客户端虽然目前看来还较为活跃,但是代码问题还是较多的,而且对于c++的支持并不是很好. 还有c++版本,虽然该客户端是按照c++的思路设计,但是最近更新时间为2013年12月19日,已经很久没有更新了. 从官方了解到,kafka作者对于现有的producer和consumer的设计是不太满意的.他们打算

ngx lua模块源码简单解析

ngx lua模块源码简单解析分类: nginx 2014-07-11 11:45 2097人阅读 评论(0) 收藏 举报nginxlua数据结构架构目录(?)[+]对nginx lua模块的整个流程,原理简单解析.由于nginx lua模块相关配置,指令,API非常多,所以本文档只以content_by_lua指令举例说明. 读本文档最好配合读源码. 不适合对nginx和lua一点都不了解的人看.1.相关配置详细配置见 https://github.com/openresty/lua-ngin

netty 源码简单分析一

周末简单看了下netty5的源码,只看懂了个大概,记录下成果,方便下次再看的时候回忆. 上服务端代码: public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.grou

Javac源码简单分析之解析和填充符号表

一.说明 符号表是由一组符号地址和符号信息构成的表格.符号表中所登记的信息在编译的不同阶段都要用到,在语义分析(后面的步骤)中,符号表所登记的内容将用于语义检查和产生中间代码,在目标代码生成阶段,党对符号名进行地址分配时,符号表是地址分配的依据. 二.主要的类与方法 解析和填充符号表这个过程主要由com.sun.tools.javac.comp.Entry及com.sun.tools.javac.comp.MemberEnter两个类来实现的. com.sun.tools.javac.comp.

Javac源码简单分析之Javac简单介绍

一.简单介绍 javac 是java语言编程编译器.javac工具读由java语言编写的类和接口的定义,并将它们编译成字节代码的class文件. 二.源码获取 OpenJDK6源码:http://download.java.net/openjdk/jdk6/ Javac的源码就在OpenJDK源码里面. 或者在CSDN下载:http://download.csdn.net/detail/p_3er/7383741 三.Javac的包 Javac的公共入口点是com.sun.tools.javac

FFmpeg源码简单分析:结构体成员管理系统-AVOption

===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFmpeg源码结构图 - 编码 [通用] FFmpeg 源码简单分析:av_register_all() FFmpeg 源码简单分析:avcodec_register_all() FFmpeg 源码简单分析:内存的分配和释放(av_malloc().av_free()等) FFmpeg 源码简单分析:常

FFmpeg源码简单分析:libswscale的sws_scale()

===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFmpeg源码结构图 - 编码 [通用] FFmpeg 源码简单分析:av_register_all() FFmpeg 源码简单分析:avcodec_register_all() FFmpeg 源码简单分析:内存的分配和释放(av_malloc().av_free()等) FFmpeg 源码简单分析:常