[简易]中英文混合排序
2016-03-29 14:39
375 查看
代码,(说明略,看注释)
输出结果
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
相关文章推荐
- 深入探讨ROP 载荷分析
- API。Spark SQL 1.3.0 DataFrame介绍、使用及提供了些完整的数据写入
- Python伪装浏览器爬虫读取网页内容
- node.js学习笔记(4)--使用Express完成简单的登陆
- 读懂这100篇论文,你也能成为大数据专家
- 用Netty开发中间件:高并发性能优化(转)
- Codeforces 639A (set 水~)
- Android小记:编码命名规范
- 如何修改Android Studio主题
- linux之vim命令
- android Palette调色板的使用方法
- AFNetWorking的实现分析以及简单使用
- 数据库处理session类
- hdu5032 Always Cook Mushroom
- POI操作Excel常用方法总结(转)
- cf#276-B - Maximum Value - (数学+暴力)/(二分)
- ionic(phonegap)-SplashScreen设置
- Shell逐行读取文件的4种方法
- Eclipse中应用Sublime主题界面
- MySQL中的外键是什么、有什么作用