范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

关于携带中文数字字符串的排序解决方案

  我们在日常的开发中,偶尔会遇到这么一种场景,那就是对携带中文数字的字符串进行排序的问题,比如:"XXX号楼XX单元XXX号"等。说实话,作为一个懒人而言,寻找成熟的工具类是最快捷和省事的方法。但是我查了很久,都未发现可用的工具类。虽然在CSDN或博客园有人分享过类似的写法,但是测试之后总是觉得不尽如人意。思量再三后,还是决定自己实现。
  其实仔细想想,排序这个事也没那么难。最重要的是想明白按照哪种规则进行排序即可。我想出的规则如下:首先建立转换的字典表,也就是常见数字、单位与对应阿拉伯数字的映射关系。比较的时候通过两个索引来从前往后依次比较对应索引处的字符,若相等,则继续进行下一位的比较。当对应索引处的字符不相等时,则判断是否为数字,如果是则各自向前推进,直到遇到非数字为止,接着将获取到的字符串数字转换为Long类型后进行比较。若判断是字母,则直接进行比较。若判断为字典表中的值,则各自向前推进,直到遇到非字典中的值后,将获取到的字符串转换为Long类型后进行比较。若3,4,5三种情况都不满足,则按照默认的中文排序。
  下面开始对应的代码实现。建立转换的字典表
  下面是建立字典表的代码:		private static Set keyList = new HashSet<>();     private static Map basicNumMap = new HashMap<>();     private static Map unitMap = new HashMap<>();     private static Map bigUnitMap = new HashMap<>();      static {         // 初始化basicNumMap         basicNumMap.put("零", 0L);         basicNumMap.put("一", 1L);         basicNumMap.put("二", 2L);         basicNumMap.put("三", 3L);         basicNumMap.put("四", 4L);         basicNumMap.put("五", 5L);         basicNumMap.put("六", 6L);         basicNumMap.put("七", 7L);         basicNumMap.put("八", 8L);         basicNumMap.put("九", 9L);         // 初始化unitMap         unitMap.put("十", 10L);         unitMap.put("百", 100L);         unitMap.put("千", 1000L);         // 初始化unitMap         bigUnitMap.put("万", 10000L);         bigUnitMap.put("亿", 1_0000_0000L);         // 初始化keyList         keyList.addAll(basicNumMap.keySet());         keyList.addAll(unitMap.keySet());         keyList.addAll(bigUnitMap.keySet());     }中文转数字
  上面说到,若对应索引处的字符为字典中的值,意味着可以转换为数字。因此需提供一个将中文数字转换为对应阿拉伯数字的方法,下面是对应的代码:/**      * 提取字符串中的数字(若存在非数字的汉字则进行忽略)      *      * @param str      * @return      */     private static long chineseToNumber(String str) {         // 若字符串为空,则返回默认值-1         if (str == null || str.length() == 0) {             return -1L;         }          /*         进行运算的栈,运算规则是:         1、若获取到的字符为非字典值,则意味着该字符串不是数字,就抛出异常         2、若为从零到九的基础数字,则直接压入栈中;         3、若为十,百,千这种普通的计数单位,则需判断栈是否为空,不为空时将栈中的数字取出与该计数单位相乘后再次压入栈中。             为空则直接将对应的计数单位压入栈中。         4、若为万,亿这种大的计数单位,则将栈中的元素进行累加后获得栈累加值,接着判断当前的大计数位是否比之前的大,             若大,则需将栈累加值与之前的全局累加值想加后再进行相乘,将计算的值赋给全局累加值。若不大,则将栈累加值与大计数单位相乘             后再与全局累加值进行相加。         5、当退出循环后,需检查操作数栈是否为空,若不为空,则将栈中的值依次取出累加到全局累计值上。、         6、将最后的全局累加值进行返回就可得到转换后的数字          */         LinkedList operateNumStack = new LinkedList<>();         long maxBigUnit = 0L;         long num = 0L, currentSum;         for (int i = 0; i < str.length(); i++) {             char currCh = str.charAt(i);             if (!keyList.contains(currCh)) {                 throw new RuntimeException("该字符串不能转换为数字");             }              if (basicNumMap.containsKey(currCh)) {                 operateNumStack.push(basicNumMap.get(currCh));             } else if (unitMap.containsKey(currCh)) {                 if (operateNumStack.isEmpty()) {                     operateNumStack.push(unitMap.get(currCh));                 } else {                     operateNumStack.push(operateNumStack.pop() * unitMap.get(currCh));                 }             }else if (bigUnitMap.containsKey(currCh)) {                 currentSum = 0L;                 while (!operateNumStack.isEmpty()) {                     currentSum += operateNumStack.pop();                 }                 Long currentBigUnit = bigUnitMap.get(currCh);                 if (currentBigUnit <= maxBigUnit) {                     num += currentSum * bigUnitMap.get(currCh);                 } else {                     num = (num + currentSum) * bigUnitMap.get(currCh);                     maxBigUnit = currentBigUnit;                 }             }         }          while (!operateNumStack.isEmpty()) {             num += operateNumStack.pop();         }         return num;     }中文字符串比较器
  对于Java来说,排序时如果不是数字或字母,则需要通过自定义比较器来实现排序。下面是获取自定义排序器的代码:/**      * 获取中文比较的比较器      *      * @return      */     public static Comparator chineseComp() {         return new Comparator() {             @Override             public int compare(String str1, String str2) {                 int i1 = 0, i2 = 0;                 StringBuilder sb1 = new StringBuilder();                 StringBuilder sb2 = new StringBuilder();                 Collator collator = Collator.getInstance(Locale.CHINESE);                 while (i1 < str1.length() && i2 < str2.length()) {                     char ch1 = str1.charAt(i1);                     char ch2 = str2.charAt(i2);                     if (ch1 == ch2) {                         i1++;                         i2++;                         continue;                     }                      if (Character.isDigit(ch1) && Character.isDigit(ch2)) {                         // 收集字符串1中的数字                         while (Character.isDigit(str1.charAt(i1)) && i1 < str1.length()) {                             sb1.append(str1.charAt(i1++));                         }                          // 收集字符串2中的数字                         while (Character.isDigit(str2.charAt(i2)) && i2 < str2.length()) {                             sb2.append(str2.charAt(i2++));                         }                         long l1 = Long.parseLong(sb1.toString());                         long l2 = Long.parseLong(sb2.toString());                         if (l1 - l2 != 0) {                             return Long.compare(l1, l2);                         }                         sb1.setLength(0);                         sb2.setLength(0);                     } else if (String.valueOf(ch1).matches("[a-zA-Z]")                             && String.valueOf(ch2).matches("[a-zA-Z]")) {                         return Character.compare(Character.toLowerCase(ch1), Character.toLowerCase(ch2));                     } else if (keyList.contains(ch1) && keyList.contains(ch2)) {                         // 收集字符串1中的数字                         while (keyList.contains(str1.charAt(i1)) && i1 < str1.length()) {                             sb1.append(str1.charAt(i1++));                         }                          // 收集字符串2中的数字                         while (keyList.contains(str2.charAt(i2)) && i2 < str2.length()) {                             sb2.append(str2.charAt(i2++));                         }                          long l1 = chineseToNumber(sb1.toString());                         long l2 = chineseToNumber(sb2.toString());                         if (l1 - l2 != 0) {                             return Long.compare(l1, l2);                         }                          sb1.setLength(0);                         sb2.setLength(0);                     } else {                         return collator.compare(Character.toString(ch1), Character.toString(ch2));                     }                  }                 return 1;             }         };     }
  到此关键的代码就已经介绍完毕,下面给出所有的代码:import java.text.Collator; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Locale; import java.util.Map; import java.util.Set;  public class ChineseCompUtils {      public static void main(String[] args) {          String[] strArr = {                 "龙跃苑一区三号楼二单元101号", "龙跃苑二区四号楼五单元201号", "龙跃苑一区八号楼六单元101号",                 "龙跃苑四区十二号楼五单元301号", "龙跃苑二区十七号楼二单元501号", "龙跃苑三区八号楼三单元401号",                 "龙跃苑一区三号楼二单元201号", "龙跃苑一区九号楼二单元601号", "龙跃苑一区二十二号楼二单元402号",                 "龙跃苑三区一号楼五单元301号", "龙跃苑三区四号楼一单元501号", "龙跃苑三区十一号楼六单元301号",                 "龙跃苑二区三号楼二单元201号", "龙跃苑四区八号楼一单元301号", "龙跃苑二区二号楼四单元301号",                 "龙跃苑四区三号楼九单元401号", "龙跃苑二区五号楼二单元201号", "龙跃苑四区二十八号楼二单元501号",                 "龙跃苑二区三号楼一单元301号", "龙跃苑一区六号楼二单元401号", "龙跃苑一区十七号楼二单元301号",                 "龙跃苑一区三号楼十七单元301号", "龙跃苑三区十一号楼二单元602号", "龙跃苑三区三号楼二单元201号",         };         Arrays.sort(strArr, chineseComp());         for (int i = 0; i < strArr.length; i++) {             System.out.println(strArr[i]);         }     }      private static Set keyList = new HashSet<>();     private static Map basicNumMap = new HashMap<>();     private static Map unitMap = new HashMap<>();     private static Map bigUnitMap = new HashMap<>();      static {         // 初始化basicNumMap         basicNumMap.put("零", 0L);         basicNumMap.put("一", 1L);         basicNumMap.put("二", 2L);         basicNumMap.put("三", 3L);         basicNumMap.put("四", 4L);         basicNumMap.put("五", 5L);         basicNumMap.put("六", 6L);         basicNumMap.put("七", 7L);         basicNumMap.put("八", 8L);         basicNumMap.put("九", 9L);         // 初始化unitMap         unitMap.put("十", 10L);         unitMap.put("百", 100L);         unitMap.put("千", 1000L);         // 初始化unitMap         bigUnitMap.put("万", 10000L);         bigUnitMap.put("亿", 1_0000_0000L);         // 初始化keyList         keyList.addAll(basicNumMap.keySet());         keyList.addAll(unitMap.keySet());         keyList.addAll(bigUnitMap.keySet());     }      /**      * 获取中文比较的比较器      *      * @return      */     public static Comparator chineseComp() {         return new Comparator() {             @Override             public int compare(String str1, String str2) {                 int i1 = 0, i2 = 0;                 StringBuilder sb1 = new StringBuilder();                 StringBuilder sb2 = new StringBuilder();                 Collator collator = Collator.getInstance(Locale.CHINESE);                 while (i1 < str1.length() && i2 < str2.length()) {                     char ch1 = str1.charAt(i1);                     char ch2 = str2.charAt(i2);                     if (ch1 == ch2) {                         i1++;                         i2++;                         continue;                     }                      if (Character.isDigit(ch1) && Character.isDigit(ch2)) {                         // 收集字符串1中的数字                         while (Character.isDigit(str1.charAt(i1)) && i1 < str1.length()) {                             sb1.append(str1.charAt(i1++));                         }                          // 收集字符串2中的数字                         while (Character.isDigit(str2.charAt(i2)) && i2 < str2.length()) {                             sb2.append(str2.charAt(i2++));                         }                         long l1 = Long.parseLong(sb1.toString());                         long l2 = Long.parseLong(sb2.toString());                         if (l1 - l2 != 0) {                             return Long.compare(l1, l2);                         }                         sb1.setLength(0);                         sb2.setLength(0);                     } else if (String.valueOf(ch1).matches("[a-zA-Z]")                             && String.valueOf(ch2).matches("[a-zA-Z]")) {                         return Character.compare(Character.toLowerCase(ch1), Character.toLowerCase(ch2));                     } else if (keyList.contains(ch1) && keyList.contains(ch2)) {                         // 收集字符串1中的数字                         while (keyList.contains(str1.charAt(i1)) && i1 < str1.length()) {                             sb1.append(str1.charAt(i1++));                         }                          // 收集字符串2中的数字                         while (keyList.contains(str2.charAt(i2)) && i2 < str2.length()) {                             sb2.append(str2.charAt(i2++));                         }                          long l1 = chineseToNumber(sb1.toString());                         long l2 = chineseToNumber(sb2.toString());                         if (l1 - l2 != 0) {                             return Long.compare(l1, l2);                         }                          sb1.setLength(0);                         sb2.setLength(0);                     } else {                         return collator.compare(Character.toString(ch1), Character.toString(ch2));                     }                 }                 return 1;             }         };     }      /**      * 提取字符串中的数字(若存在非数字的汉字则进行忽略)      *      * @param str      * @return      */     private static long chineseToNumber(String str) {         // 若字符串为空,则返回默认值-1         if (str == null || str.length() == 0) {             return -1L;         }          /*         进行运算的栈,运算规则是:         1、若获取到的字符未非字典值,意味着该字符串不是数字,就抛出异常         2、若为从零到九的基础数字,则直接压入栈中;         3、若为十,百,千这种普通的计数单位,则需判断栈是否为空,不为空时将栈中的数字取出与该计数单位相乘后再次压入栈中。             为空则直接将对应的计数单位压入栈中。         4、若为万,亿这种大的计数单位,则将栈中的元素进行累加后获得栈累加值,接着判断当前的大计数位是否比之前的大,             若大,则需将栈累加值与之前的全局累加值想加后再进行相乘,将计算的值赋给全局累加值。若不大,则将栈累加值与大计数单位相乘             后再与全局累加值进行相加。         5、当退出循环后,需检查操作数栈是否为空,若不为空,则将栈中的值依次取出累加到全局累计值上。、         6、将最后的全局累加值进行返回就可得到转换后的数字          */         LinkedList operateNumStack = new LinkedList<>();      // 操作数栈         long maxBigUnit = 0L;         long num = 0L, currentSum;         for (int i = 0; i < str.length(); i++) {             char currCh = str.charAt(i);             if (!keyList.contains(currCh)) {                 throw new RuntimeException("该字符串不能转换为数字");             }              if (basicNumMap.containsKey(currCh)) {                 operateNumStack.push(basicNumMap.get(currCh));             } else if (unitMap.containsKey(currCh)) {                 if (operateNumStack.isEmpty()) {                     operateNumStack.push(unitMap.get(currCh));                 } else {                     operateNumStack.push(operateNumStack.pop() * unitMap.get(currCh));                 }             } else if (bigUnitMap.containsKey(currCh)) {                 currentSum = 0L;                 while (!operateNumStack.isEmpty()) {                     currentSum += operateNumStack.pop();                 }                 Long currentBigUnit = bigUnitMap.get(currCh);                 if (currentBigUnit <= maxBigUnit) {                     num += currentSum * bigUnitMap.get(currCh);                 } else {                     num = (num + currentSum) * bigUnitMap.get(currCh);                     maxBigUnit = currentBigUnit;                 }             }         }          while (!operateNumStack.isEmpty()) {             num += operateNumStack.pop();         }         return num;     } }
  执行结果如下所示:

OPPOFindX5Pro,玩的就是曲线,颜值必须做到极致我个人对于OPPO还是非常欣赏的,在如今大家都在堆料的竞争中,它会给到我一种行业清流的感觉。Find系列机型相信大家也都接触过了,大多数产品的曲线设计是得到了消费者认可的,非常具有中国移动大方了?10年不换号的老用户,现能享受4个特权中国移动一直以来在人民心目中的形象算不上非常好。不管是业务办理上,还是服务质量上都被很多人吐槽过。信号也不算特别好,很多时候信号突然会中断,可以说在使用上让人非常苦恼。不过中国移动安徽大学研发出全球领先机器人智能抓取装置记者5月6日从安徽大学获悉,该校电气工程与自动化学院陈文杰教授团队基于机构具身性智能理论,提出了一套创新并联自适应抓手设计技术,成功研发出针对异状零件抓取作业的多个系列单驱自适应多我对中概互联网投资的反思2021年底我所写的关于互联网公司投资价值的思考文章,目前回溯来看,当时极度低估了中概股在美国的退市风险,也进一步充满了对政策的敬畏,不是一切判断都可以来源于逻辑的,深刻的发现了自被质疑割韭菜!知识付费的生意还能做多久?来源中国青年报自从2013年,公众号罗辑思维推出付费会员制以来,知识付费一词便跃入大众的视野中。其后近10年间,我国知识付费行业这片蓝海以令人目眩的速度扩张。数据显示,2021年,Java16新特性instanceof增强instanceof这个关键词,主要用来判断某个对象是不是某个类的实例。比如,有时候我们要处理一个类似这样的数据集MapString,ObjectdatanewHashMap()d数据治理大数据湖仓一体开源框架数据治理大数据湖仓一体开源框架分为4部分1数据源业务库数据用户日志系统日志爬虫数据2构建集群Hadoop,HDFS,Yarn3。1数据采集数据采集工具SqoopFlumeCanal软件测试工程师常见面试题2一,oracle与mysql数据库区别1。mysql中小型开源,oracle大型收费2。Mysql有自动增长的数据类型,oracle没有3。mysql默认不支持事物oracle是完重磅!Gucci宣布接受比特币狗狗币支付目前的最新消息奢侈品牌GUCCI也要开始接受加密货币的支付了!根据最新的情报显示,GUCCI此举率先会在美国开始试点,从本月底开始。第一批支持加密货比的GUCCI门店位于纽约的WoPHP中arraysplice()函数对数组元素的添加修改删除arraysplice()函数从数组中可实现对数据中元素的添加修改删除操作,方便对数组中的值进行处理。语法arraysplice(array,start,length,array)姚记科技务实进取,泛娱乐王国横空出世今天我们来聊聊旧貌换新颜的泛娱乐龙头姚记科技。经常打牌的朋友对这个名字一定不陌生,这家公司之前就叫姚记扑克,从上世纪90年代起就以扑克牌生产发家致富,如今已经具备规模效应与成本优势
比纸还轻,真的好听!GIECCandyPods耳机体验年少不屑影碟机,轻装上阵才自由玩过DVD的人,十有八九接触过老牌厂家杰科(GIEC)。70后亲爹书房光碟一摞摞,用的就是GIEC的影碟机。可惜时光一去不回头,如今我们看片用W盘讯X远程办公不求人,向日葵开机插座测评前几天在网上看到有人用手机或者平板电脑远程控制电脑的文章,看到之后自己心动不已,在经过一系列探查之后发现其实操作并不困难。下载国民远控软件向日葵远程控制就能搞定,有点像之前QQ的远10年家居设计师测评,米家bMOLA空气净化器有何特别关键看这点我们生活中的雾霾沙尘花粉柳絮yi情肆意层出不穷的空气质量问题,导致越来越多家庭选择购买空气净化器。作为一名从业了10年的设计师,在家居家电领域颇有研究,想聊聊米家bMOLA空气净化双屏显示真的爽!北弧E5002双屏显示器支架安装体验双屏显示真的爽,值友诚不我欺!北弧E5002双屏显示器支架安装体验大家好,我是噩梦飘雷关注我,后续分享更多折腾经验前文讲到,最近由于疫情因素,宅家的时间大大增加,想给电脑添加一个显华为笔记本电脑一个月主板坏了3月24购买一台笔记本电脑,4月28日出现阶段性卡顿现象,键盘输入乱码,充电口接触不良等现象,已不能使用,5月2日到华为官方售后检测说需要更换电脑主板,售后给的回复就是只能维修,更恒大汽车遭疯抢?曝预售10小时爆单5万台!网友没找到订车入口5月9日消息,近期有报道称,恒大汽车旗下恒驰品牌近期开启预售,盲订后10小时内订单就达到5万辆。该消息一经曝光就引起了网友的广泛议论,有网友表示,并没有看到有关恒驰5的订车入口,并安森美等暂不接单,车用IGBT芯片短缺严峻芯片短缺于2020年底从汽车行业开始蔓延到涉及半导体的各个领域,而今,一年多过去之后,汽车行业的芯片短缺仍然处于深水区。最近,据财联社报道,安森美深圳工厂内部人士称车用绝缘栅双极晶理想汽车被曝毁约校招生,官方回应因业务调整,提供调岗或赔偿Tech星球5月11日消息,近日有网友在社交平台曝光,称理想汽车毁约校招生,据网友曝光的邮件内容透露,解约原因是由于理想汽车近期对业务架构进行调整,目前公司没有相关匹配的岗位。对此理想汽车回应校招生被拒因业务有调整提供调岗或解约赔偿新京报贝壳财经讯有用户在脉脉等平台透露,理想汽车在5月毁约了2022年毕业的校招生,其中不少人已经和理想汽车学校签署了三方协议,准备等着毕业答辩结束后入职。对此,理想汽车回应称这个js基础面试题221240道题目221。什么是假值对象?参考答案浏览器在某些特定情况下,在常规JavaScript语法基础上自己创建了一些外来值,这些就是假值对象。假值对象看起来和普通对象并无二致(都有属性,等等js基础面试题131160道题目131。用原生JavaScript的实现过什么功能吗?参考答案轮播图手风琴放大镜3D动画效果等,切记,所答的一定要知道实现原理!,不知道还不如不说!参与互动132。javascri