<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      【踩坑系列】使用Comparator.comparing對中文字符串排序結果不對

      2025-04-25 13:18  申城異鄉人  閱讀(328)  評論(0)    收藏  舉報

      1. 踩坑經歷

      假設有這樣一個業務場景,需要對各個城市的訂單量排序,排序規則為:

      先根據訂單量倒序排列,再根據城市名稱正序排列。

      示例代碼:

      import lombok.Getter;
      import lombok.Setter;
      import lombok.ToString;
      
      @Getter
      @Setter
      @ToString
      public class OrderStatisticsInfo {
          private String cityName;
          private Integer orderCount;
      
          public OrderStatisticsInfo(String cityName, Integer orderCount) {
              this.cityName = cityName;
              this.orderCount = orderCount;
          }
      }
      
      public static void main(String[] args) {
          List<OrderStatisticsInfo> orderStatisticsInfoList = Arrays.asList(
                  new OrderStatisticsInfo("上海", 1000),
                  new OrderStatisticsInfo("北京", 1000),
                  new OrderStatisticsInfo("成都", 700),
                  new OrderStatisticsInfo("常州", 700),
                  new OrderStatisticsInfo("廣州", 900),
                  new OrderStatisticsInfo("深圳", 800)
          );
      
          orderStatisticsInfoList.sort(Comparator.comparing(OrderStatisticsInfo::getOrderCount, Comparator.reverseOrder())
                  .thenComparing(OrderStatisticsInfo::getCityName));
          orderStatisticsInfoList.forEach(System.out::println);
      }
      

      預期結果:

      北京 1000

      上海 1000

      廣州 900

      深圳 800

      常州 700

      成都 700

      實際結果:

      OrderStatisticsInfo(cityName=上海, orderCount=1000)
      OrderStatisticsInfo(cityName=北京, orderCount=1000)
      OrderStatisticsInfo(cityName=廣州, orderCount=900)
      OrderStatisticsInfo(cityName=深圳, orderCount=800)
      OrderStatisticsInfo(cityName=常州, orderCount=700)
      OrderStatisticsInfo(cityName=成都, orderCount=700)

      從以上結果可以看出,根據訂單量倒序排列沒啥問題,但根據城市名稱正序排列不符合預期:

      上海竟然排到了北京的前面,但常州與成都的順序又是對的。

      2. 原因分析

      Comparator.comparing對字符串類型進行排序時,默認使用的是字符串的自然排序,即StringcompareTo方法,該方法是基于

      Unicode編碼值進行比較的,未考慮語言特定的字符順序(如中文拼音)。

      先看下StringcompareTo方法的源碼:

      public int compareTo(String anotherString) {
          int len1 = value.length;
          int len2 = anotherString.value.length;
          int lim = Math.min(len1, len2);
          char v1[] = value;
          char v2[] = anotherString.value;
      
          int k = 0;
          while (k < lim) {
              char c1 = v1[k];
              char c2 = v2[k];
              if (c1 != c2) {
                  return c1 - c2;
              }
              k++;
          }
          return len1 - len2;
      }
      

      以上海與北京的比較為例,先比較第一個字符,也就是字符上和字符北,字符上對應的Unicode編碼值是19978,因此c1 = 19978,

      字符北對應的Unicode編碼值是21271,因此c2 = 21271,因為c1 != c2,所以返回值為-1293,

      也就是說上海小于北京(要排在北京的前面),不符合預期。

      以常州與成都的比較為例,先比較第一個字符,也就是字符常和字符成,字符常對應的Unicode編碼值是24120,因此c1 = 24120,

      字符成對應的Unicode編碼值是25104,因此c2 = 25104,因為c1 != c2,所以返回值為-984,

      也就是說常州小于成都(要排在成都的前面),符合預期。

      可以通過Character.codePointAt方法獲取字符的Unicode編碼值:

      // 輸出:19978
      System.out.println(Character.codePointAt("上海", 0));
      // 輸出:21271
      System.out.println(Character.codePointAt("北京", 0));
      // 輸出:24120
      System.out.println(Character.codePointAt("常州", 0));
      // 輸出:25104
      System.out.println(Character.codePointAt("成都", 0));
      

      3. 解決方案

      Java提供了本地化的排序規則,可以按特定語言規則排序(如中文拼音),代碼如下所示:

      orderStatisticsInfoList.sort(Comparator.comparing(OrderStatisticsInfo::getOrderCount, Comparator.reverseOrder())
                      .thenComparing(OrderStatisticsInfo::getCityName, Collator.getInstance(Locale.CHINA)));
      orderStatisticsInfoList.forEach(System.out::println);
      

      此時的輸出結果為:

      OrderStatisticsInfo(cityName=北京, orderCount=1000)
      OrderStatisticsInfo(cityName=上海, orderCount=1000)
      OrderStatisticsInfo(cityName=廣州, orderCount=900)
      OrderStatisticsInfo(cityName=深圳, orderCount=800)
      OrderStatisticsInfo(cityName=常州, orderCount=700)
      OrderStatisticsInfo(cityName=成都, orderCount=700)

      可以看到,北京排到了上海的前面,符合預期。

      上述代碼指定了Collator.getInstance(Locale.CHINA),在排序比較時不再執行StringcompareTo方法,

      而是執行Collatorcompare方法,實際上是RuleBasedCollatorcompare方法。

      可以執行以下代碼單獨看下上海與北京的比較結果:

      Collator collator = Collator.getInstance(Locale.CHINA);
      // 輸出:1,代表上海大于北京,也就是要排在北京的后面
      System.out.println(collator.compare("上海", "北京"));
      

      文章持續更新,歡迎關注微信公眾號「申城異鄉人」第一時間閱讀!

      主站蜘蛛池模板: 一本精品中文字幕在线| 免费看欧美全黄成人片| 久久精品国产一区二区三| 真人性囗交视频| 亚洲欧美v国产一区二区| 乱色欧美激惰| h无码精品3d动漫在线观看| 97国产成人无码精品久久久| 亚洲欧美偷国产日韩| 久久人妻无码一区二区三区av| 亚洲熟妇精品一区二区| 少妇被躁爽到高潮| 国产学生裸体无遮挡免费| 国产成人亚洲欧美二区综合| 国产在线永久视频| 极品蜜桃臀一区二区av| 亚洲区综合中文字幕日日| 国精品无码一区二区三区在线看| 日日猛噜噜狠狠扒开双腿小说| 国产成人精品性色av麻豆| 国产精品久久久久久无毒不卡 | 内射极品少妇xxxxxhd| 激情综合网激情国产av| 欧美人与禽2o2o性论交| 欧美牲交videossexeso欧美| 国产成人精品视频网站| 国产色无码精品视频免费| 成 年 人 黄 色 大 片大 全| 国产在线中文字幕精品| 色爱综合激情五月激情| 丹江口市| 无码国产偷倩在线播放老年人| 69天堂人成无码免费视频 | 欧美性猛交xxxx富婆| 噜噜噜噜私人影院| 国产成人精品一区二区无| 亚洲国产日韩一区三区| 男女啪啪永久免费观看网站| 成人区人妻精品一区二区| 国产情侣激情在线对白| 大埔县|