浅析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;
    }

 

就是如下图的资源:

 

http://www.cnblogs.com/sphere/p/4738888.html

 

时间: 2024-08-01 09:31:14

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

深入浅析knockout源码分析之订阅_javascript技巧

Knockout.js是什么? Knockout是一款很优秀的JavaScript库,它可以帮助你仅使用一个清晰整洁的底层数据模型(data model)即可创建一个富文本且具有良好的显示和编辑功能的用户界面.任何时候你的局部UI内容需要自动更新(比如:依赖于用户行为的改变或者外部的数据源发生变化),KO都可以很简单的帮你实现,并且非常易于维护. 一.主类关系图 二.类职责 2.1.observable(普通监控对象类) observable(他其是一个function)的内部实现: 1.首先声

Android View事件分发和消费源码简单理解

Android View事件分发和消费源码简单理解 前言: 开发过程中觉得View事件这块是特别烧脑的,看了好久,才自认为看明白.中间上网查了下singwhatiwanna粉丝的读书笔记,有种茅塞顿开的感觉. 很重要的学习方法:化繁为简,只抓重点. 源码一坨,不要指望每一行代码都看懂.首先是没必要,其次大量非关键代码会让你模糊真正重要的部分. 以下也只是学姐的学习成果,各位同学要想理解深刻,还需要自己亲自去看源码. 2.源码分析 由于源码实在太长,而且也不容易看懂,学姐这里就不贴出来了,因为没必

VBS利用SendKeys输入中文字符的方法_vbs

  首先我们看一个输入字母的例子: 复制代码 代码如下: set s = WScript.CreateObject("WScript.Shell") app=s.Run ("C:\windows\notepad.exe") code="biweilun" WScript.Sleep 1000 s.AppActivate app s.SendKeys code Wscript.quit 这段vbs会SendKeys方法的朋友就知道,作用是打开一个记

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

微信网页授权(OAuth2.0) PHP 源码简单实现_php实例

提要:  1. 建议对OAuth2.0协议做一个学习.  2. 微信官方文档和微信官网工具要得到充分利用.  比较简单,直接帖源代码了.其中"xxxxxxxxxx"部分,是需要依据自己环境做替换的 /** * OAuth2.0微信授权登录实现 * * @author zzy * @文件名:GetWxUserInfo.php */ // 回调地址 $url = urlencode("http://www.xxxxxxxxx.com/GetWxUserInfo.php"

浅析200源码网的营销策略

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 对苦苦等待我更新文章的朋友们,真心说声抱歉!这篇文章是我今年写的第一篇文章,因为自己要做自己的项目时间比较紧,所以没有来得及更新,真是抱歉,当然我不会忘记你们曾经对我默默的支持.最近都有朋友看到以前的文章来加我Q,说给他很大的启发,其实这也是我最开心的事情,如果我的文章可以帮助你提高你的思维,帮助你少走弯路就心满意足,当然也有朋友说反对我,你

微信网页授权(OAuth2.0) PHP 源码简单实现

提要:  1. 建议对OAuth2.0协议做一个学习.  2. 微信官方文档和微信官网工具要得到充分利用.  比较简单,直接帖源代码了.其中"xxxxxxxxxx"部分,是需要依据自己环境做替换的 /** * OAuth2.0微信授权登录实现 * * @author zzy * @文件名:GetWxUserInfo.php */ // 回调地址 $url = urlencode("http://www.xxxxxxxxx.com/GetWxUserInfo.php"

收藏了4年的Android 源码分享

Android 超过2个G的源代码集合~~几乎涵盖了所有功能效果的实现,一应俱全~~应有尽有~~ 360云盘地址:Android 各类源码集合汇总 (提取码:f930) 另外,附上Github上及自己整理的一些代码集合~~ Android手势处理集合框架 源码 Android 一个简单的缓存框架 源码 Android 一个流畅的PDF阅读器 源码 Android 利用精简Zxing实现条形码/二维码 扫描Demo Android 水波特效(录音功能) 源码 SlidMenu 侧滑菜单.ViewP

收藏了4年的android app源码下载

Android 超过2个G的源代码集合~~几乎涵盖了所有功能效果的实现,一应俱全~~应有尽有~~ 360云盘地址:Android 各类源码集合汇总 (提取码:f930) 另外,附上Github上及自己整理的一些代码集合~~ Android手势处理集合框架 源码 Android 一个简单的缓存框架 源码 Android 一个流畅的PDF阅读器 源码 Android 利用精简Zxing实现条形码/二维码 扫描Demo Android 水波特效(录音功能) 源码 SlidMenu 侧滑菜单.ViewP