【问题标题】:Java program to sort a versioning string in an ascending order [closed]Java程序以升序对版本控制字符串进行排序[关闭]
【发布时间】:2020-11-22 03:47:54
【问题描述】:

我有一个包含版本字符串的列表,例如:

List<String> versions_list = Arrays.asList("1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2");

我想对其进行排序,所以结果会是这样的:

["1.0.0", "1.0.2", "1.0.12", "1.1.2", "1.3.3"]

如何在 Java 中做到这一点。

【问题讨论】:

  • 首先,提供一个有效的Java代码。
  • 是否保证版本始终采用A.B.CA.BA.B.C.D 等形式?

标签: java sorting versioning


【解决方案1】:

这是使用 Comparator 的 lambda 的一种方法。处理不同长度的版本 ID。

Comparator<String> comp = (a, b) -> {
    String[] aa = a.split("\\.");
    String[] bb = b.split("\\.");
    int r = 0;
    for (int i = 0; i < Math.min(aa.length, bb.length); i++) {
        r = Integer
                .compare(Integer.valueOf(aa[i]),Integer.valueOf(bb[i]));
        if (r != 0) {
            return r;
        }
    }
    return Integer.compare(aa.length, bb.length);
};
            
List<String> versions_list = Arrays.asList("1.1.2", "1.0.0",
        "1.3.3", "1.0.12", "1.0.0.12", "1.1.0.2", "1.0.2", "1.2.1.2.3");
versions_list.sort(comp);
System.out.println(versions_list);

打印

[1.0.0, 1.0.0.12, 1.0.2, 1.0.12, 1.1.0.2, 1.1.2, 1.2.1.2.3, 1.3.3]

【讨论】:

    【解决方案2】:

    这是一个现代的解决方案,使用Comparator.comparing构建版本字符串比较器,基于预先存在的标准库Arrays.compare(int[])方法。

        List<String> versionList = Arrays.asList("1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2");
    
        Pattern pattern = Pattern.compile("\\.");
        Comparator<String> versionComparator = Comparator.comparing(
            str -> pattern.splitAsStream(str)
                .mapToInt(Integer::parseInt)
                .toArray(),
            Arrays::compare);
        versionList.sort(versionComparator);
        
        System.out.println(versionList);
    

    【讨论】:

      【解决方案3】:
      public static void main(String[] args) {
          String[] versions_list = {"1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2"};
          Arrays.sort(versions_list, (o1, o2) -> {
              String[] str1 = o1.split("\\.");
              String[] str2 = o2.split("\\.");
              if (!Integer.valueOf(str1[0]).equals(Integer.valueOf(str2[0])))
                  return Integer.valueOf(str1[0]) - Integer.valueOf(str2[0]);
              if (!Integer.valueOf(str1[1]).equals(Integer.valueOf(str2[1])))
                  return Integer.valueOf(str1[1]) - Integer.valueOf(str2[1]);
              return Integer.valueOf(str1[2]) - Integer.valueOf(str2[2]);
          });
          for (String str : versions_list) {
              System.out.println(str);
          }
      }
      

      对不起,我又写代码了 输出:1.0.0 1.0.2 1.0.12 1.1.2 1.3.3,你也用循环来做!

      【讨论】:

      • 不要重新发布新答案。只需更正您的旧版本即可。
      • 好吧,我更新鲜了。
      • 我应该编辑我的旧答案吗?
      • 没有。这次不行。别担心。欢迎来到 Stack Overflow。 :)
      • 好的,谢谢!我记得。
      【解决方案4】:

      您可以使用Comparator 执行此操作,如下所示:

          List<String> sorted = List.of("1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2")
                  .stream()
                  .sorted((s1, s2) -> {
                      String[] s1Parts = s1.split("\\.");
                      String[] s2Parts = s2.split("\\.");
      
                      Integer[] s1IntParts = Arrays.stream(s1Parts).map(Integer::parseInt).toArray(Integer[]::new);
                      Integer[] s2IntParts = Arrays.stream(s2Parts).map(Integer::parseInt).toArray(Integer[]::new);
      
                      int comparisonResult = -1;
                      for (int i=0; i<3; i++) {
                          comparisonResult = Integer.compare(s1IntParts[i], s2IntParts[i]);
                          if (comparisonResult != 0) {
                              break;
                          }
                      }
                      return comparisonResult;
                  })
                  .collect(Collectors.toList());
      

      【讨论】:

        【解决方案5】:

        假设:

        List<String> versions = Arrays.asList("1.1.2", "1.0.0", "1.3.3", "1.0.12", "1.0.2");
        

        您应该使用自定义Comparator,只要默认比较器不能应用于这种类型的字符串,否则数字将不会按数字排序(例如,12 被认为低于2

        versions.sort(new Comparator<String>() {
            @Override
            public int compare(final String l, final String r) {
                String[] left = l.split("\\.");
                String[] right = r.split("\\.");
                int iterableLength = Math.min(left.length, right.length);
                for (int i=0; i<iterableLength; i++) {
                    if (!left[i].equals(right[i])) {
                        return Integer.parseInt(left[i]) - Integer.parseInt(right[i]);
                    }
                }
                return 0;
            }
        });
        

        ...使用 lambda 表达式...

        versions.sort((l, r) -> {
            String[] left = l.split("\\.");
            String[] right = r.split("\\.");
            int iterableLength = Math.min(left.length, right.length);
            for (int i=0; i<iterableLength; i++) {
                if (!left[i].equals(right[i])) {
                    return Integer.parseInt(left[i]) - Integer.parseInt(right[i]);
                }
            }
            return 0;
        });
        

        这是一个非常简单的解决方案,使用正则表达式将版本符号拆分为 3 个单独的部分。每个不相等的部分都是数字比较的主题,因此需要Integer.parseInt(String)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-03-21
          • 2013-10-28
          • 1970-01-01
          • 2021-05-17
          • 1970-01-01
          • 2013-06-20
          相关资源
          最近更新 更多