[简易]中英文混合排序

代码,(说明略,看注释)

package utils;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * 【简易】中英文混合列表,首字母排序<br> 
 * 〈支持GBK中文编码范围 45217 - 55289 (十进制)〉
 */
public class StringSortUtils {

    public static void main(String[] args) {
        StringSortUtils sort = new StringSortUtils();
        List<String> list = new ArrayList<String>();  
        list.add("adisen-A");  
        list.add("bulsi-B");  
        list.add("Kobe-K");  
        list.add("布丁-B");  
        list.add("杜甫-D");
        list.add("宝马-B");
        list.add("奔词-B");
        list.add("比尔-B");
        list.add("嚓的撒-C");// 多音字,不在该范围内
        list.add("换手机-H");
        list.add("天明-T");
        list.add("吧马-B");
        list.add("元方-Y"); 
        list.add("芭吧-B"); 
        list.add("分割-F"); 
        list.add("割列-G"); 
        list.add("啊-A");
        list.add("#-0");
        list.add("京东-J");
        list.add("亚马逊-Y");
        list.add("撒旦-S");
        List<String> newList = sort.sort(list);
        for (String string : newList) {
            System.out.println(string);
        }

        System.out.println("-----------------------分割线-----------------------");

        Map<String, List<String>> map = sort.sortAsMap(newList, TYPE_UPPERCASE);
        String[] uppercaseTable = {
                "A", "B", "C", "D", "E", "F", "G", "H", "I",  
                "J", "K", "L", "M", "N", "O", "P", "Q", "R", 
                "S", "T", "U", "V", "W", "X", "Y", "Z", "0"  
            };
        for (String string : uppercaseTable) {
            System.out.println(string + " : " + map.get(string));
        }

        // 例举:不在范围内的中文字符
        System.out.println(sort.getGBValue('嚓'));
        System.out.println(sort.getAlpha('嚓', 0));
        System.out.println(sort.getGBValue('僮'));
        System.out.println(sort.getAlpha('僮', 0));
        System.out.println(sort.getGBValue('咗'));
        System.out.println(sort.getAlpha('咗', 0));
    }

    public static final int TYPE_UPPERCASE = 0;

    public static final int TYPE_LOWERCASE = 1;

    // 默认匹配字符串数组
    // 大写字符串数组
    // 未匹配任何字母的,匹配0,排在最后
    private String[] uppercaseTable = {
        "A", "B", "C", "D", "E", "F", "G", "H", "I",  
        "J", "K", "L", "M", "N", "O", "P", "Q", "R", 
        "S", "T", "U", "V", "W", "X", "Y", "Z", "0"  
    };

    // 小写字符串数组
    // 未匹配任何字母的,匹配0,排在最后
    private String[] lowercaseTable = {
        "a", "b", "c", "d", "e", "f", "g", "h", "i",  
        "j", "k", "l", "m", "n", "o", "p", "q", "r", 
        "s", "t", "u", "v", "w", "x", "y", "z", "0"  
    };

    /*
     * 1. 字母Z使用了两个标签,这里有27个值  
     * 2. i, u, v都不做声母, 跟随前面的字母  
     * 3. 中文定义根据GBK编码规律,选取对应26个字母发音的第一个中文,第27个为Z字母的最后一个中文,
     * 例: 阿-45218,在 A-啊-45217和B-芭-45253内
     * 
     * 注意:还有很多字不在按照此规律,不在改范围内,例如:多音字-嚓 ca cha -57578
     * 
     * 对应GBK的值:
     * 啊 : 45217 芭 : 45253 擦 : 45761 搭 : 46318 蛾 : 46826 发 : 47010 噶 : 47297 哈 : 47614 哈 : 47614
     * 击 : 48119 喀 : 49062 垃 : 49324 妈 : 49896 拿 : 50371 哦 : 50614 啪 : 50622 期 : 50906 然 : 51387
     * 撒 : 51446 塌 : 52218 塌 : 52218 塌 : 52218 挖 : 52698 昔 : 52980 压 : 53689 匝 : 54481 座 : 55289
     * }
     */
    private char[] chartable = {  
        '啊', '芭', '擦', '搭', '蛾', '发', '噶', '哈', '哈',  
        '击', '喀', '垃', '妈', '拿', '哦', '啪', '期', '然',  
        '撒', '塌', '塌', '塌', '挖', '昔', '压', '匝', '座'
        };

    /* 初始化数组  
     * 明白了原理,可以去除 chartable 和代码块,简化为 :
     * private int[] table = {
     *      45217,45253,45761,46318,46826,47010,47297,47614,47614,
     *      48119,49062,49324,49896,50371,50614,50622,50906,51387,
     *      51446,52218,52218,52218,52698,52980,53689,54481,55289
     * };
     */
    private int[] table = new int[27]; 

    {  
        // 普通代码块
        for (int i = 0; i < 27; ++i) {  
            table[i] = getGBValue(chartable[i]);  
        }  
    } 


    public StringSortUtils() {

    }

    /**
     * 获取GBK(或gb2312)的汉字编码 <br>
     * 〈gbk中文占两个字节,英文占一个字节,当得到一个字节时,返回0〉
     * <pre>
     *  getGBValue("吧") = 45257
     * </pre>
     */
    private int getGBValue(char ch){
        String str = ch + "";
        try{
            byte[] bytes = str.getBytes("GBK");
            if(bytes.length < 2) 
                return 0;
            // 0xff00 = 65280, 0xff = 255
            return (bytes[0] << 8 & 0xff00) + (bytes[1] & 0xff);
        }catch(UnsupportedEncodingException e) {
            return 0;
        }
    }

    /**
     * 中英文混合列表排序 <br>
     * 〈对中英文混合列表按照首字母排序〉
     */
    public List<String> sort(List<String> list) {
        List<String> result = new ArrayList<String>();
        for(String str : uppercaseTable) {
            for (int i = 0; i < list.size(); i++) {
                if(str.equals(getAlpha(list.get(i).toString().charAt(0), TYPE_UPPERCASE))) {
                    result.add(list.get(i).toString());
                    list.remove(i);
                    i--;
                }
            }
        }
        return result;
    }

    /**
     * 排序,返回Map<br>
     * 〈字符串列表,按照首字符的首字母进行排序,返回按照英文字母归类的Map,Map的value值是对应英文字母下的字符串列表〉
     *
     * @param list
     * @param type 类型 -- 大/小写(TYPE_UPCASE / TYPE_LOWERCASE)(0/1)
     * @return Map<String, List<String>>
     */
    public Map<String, List<String>> sortAsMap(List<String> list, int type){
        Map<String, List<String>> resultMap = new HashMap<String, List<String>>();
        List<String> arr = new ArrayList<String>();
        String [] table = (type == TYPE_UPPERCASE) ? uppercaseTable : lowercaseTable;
        for(String str : table) {
            for (int i = 0; i < list.size(); i++) {
                if(str.equals(getAlpha(list.get(i).toString().charAt(0), type))) {
                    arr.add(list.get(i).toString());
                    list.remove(i);
                    i--;
                }
            }
            resultMap.put(str, arr);
            arr = new ArrayList<String>(); 
        }
        return resultMap;
    }

    /**
     * 得到字符串的第一个字符的首字母<br>
     * <pre>
     *  英文字母返回对应的大小写字母,中文按照大小对比,判断该字的首字母.
     *  例: 啊(45217) < 阿(45218) < 芭(45253)
     *      getAlpha('阿',TYPE_UPPERCASE) == A
     * </pre>
     */
    public String getAlpha(char ch, int type) {
        // 英文字母返回对应的大小写字母
        if(ch >= 'a' && ch <= 'z') {
            return TYPE_UPPERCASE == type ? (char)(ch - 'a' + 'A') + "" : ch + "";
        }
        if(ch >= 'A' && ch <= 'Z'){
            return TYPE_UPPERCASE == type ? ch + "" : (char)(ch - 'A' + 'a') + "";
        }
        // 如果该字符不在支持的中文字符编码范围内,又不为英文字母
        int gb = getGBValue(ch);
        if(gb < table[0] || gb > table[26])
            return "0";
        // 遍历得到字符首字母对应 table 数组的位置
        int i;
        for(i = 0; i < 26; ++i) {
            if(match(i, gb))
                break;
        }
        if(i >= 26) {
            return "0";
        } else {
            return TYPE_UPPERCASE == type ? uppercaseTable[i] + "" : lowercaseTable[i] + "";
        }
    }

    private boolean match(int i, int gb) {
        if(gb < table[i])
            return false;
        int j = i + 1;
        // 遇到不发声的首字母
        while(j < 26 && (table[j] == table[i]))
            ++j;
        // 字母Z使用了两个标签
        return j == 26 ? gb <= table[j] : gb < table[j];
    }
}

输出结果

adisen-A-A
bulsi-B
布丁-B
宝马-B
奔词-B
比尔-B
吧马-B
芭吧-B
杜甫-D
分割-F
割列-G
换手机-H
京东-J
Kobe-K
撒旦-S
天明-T
元方-Y
亚马逊-Y
嚓的撒-C
#-0
-----------------------分割线-----------------------
A : [adisen-A, 啊-A]
B : [bulsi-B, 布丁-B, 宝马-B, 奔词-B, 比尔-B, 吧马-B, 芭吧-B]
C : []
D : [杜甫-D]
E : []
F : [分割-F]
G : [割列-G]
H : [换手机-H]
I : []
J : [京东-J]
K : [Kobe-K]
L : []
M : []
N : []
O : []
P : []
Q : []
R : []
S : [撒旦-S]
T : [天明-T]
U : []
V : []
W : []
X : []
Y : [元方-Y, 亚马逊-Y]
Z : []
0 : [嚓的撒-C, #-0]
57578
0
55767
0
34296
0
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值