Java中字符串的比较和排序

3

我有一个字符串数组:15MB、12MB、1TB、1GB。我想按照字典顺序进行比较,只需遵循MB小于GB和TB的规则即可。所以最后我想得到的是:12MB、15MB、1GB、1TB。我找到了一种比较字母的方法:

 final static String ORDER="MGT";

public int compare(String o1, String o2) {
       int pos1 = 0;
       int pos2 = 0;
       for (int i = 0; i < Math.min(o1.length(), o2.length()) && pos1 == pos2; i++) {
          pos1 = ORDER.indexOf(o1.charAt(i));
          pos2 = ORDER.indexOf(o2.charAt(i));
       }

       if (pos1 == pos2 && o1.length() != o2.length()) {
           return o1.length() - o2.length();
       }

       return pos1  - pos2  ;
    }

我想通过数字和字母将字符串进行分割,但是如何按字母"M B .."的顺序排序,然后按它们的数字排序。我需要使用两个比较器还是其他方法?

请看这里:https://dev59.com/u2Yr5IYBdhLWcg3wE2Sz 那里有一个有趣的解决方案。 - Laguh
已经完成了,但是它们只比较数字而不是字母。 - bfury
3个回答

1

如果你首先将数据转换为通用单位(例如MB),那么比较就会变得更加容易。如果在此转换后值相同,则应该应用词典排序,它可能看起来像这样:

private int convertToMegaBytes(String s) {

    char c = s.charAt(s.length() - 2);

    if(c == 'G')
        return 1024 * Integer.parseInt(s.substring(0, s.length() - 2));
    if(c == 'T')
        return 1024 * 1024 * Integer.parseInt(s.substring(0, s.length() - 2));

    return Integer.parseInt(s.substring(0, s.length() - 2));

}

final static String ORDER = "MGT";

public int compare(String o1, String o2) {
    int v = convertToMegaBytes(o1)  - convertToMegaBytes(o2);
    // if values are equal then compare lexicographically
    return v == 0 ? ORDER.indexOf(o1.charAt(o1.length() - 2)) - ORDER.indexOf(o2.charAt(o2.length() - 2)) : v;
}

这很有帮助,但不是我想要做的。我只需要比较给定的值而不是解析它们。例如,如果我得到了1GB、1024MB,我仍然需要按照这样的顺序进行排序:1024MB、1GB。 - bfury

0

现在按照单位和单位内的值进行排序。这是根据原始发布者的最后一条评论进行更改的。

import java.util.*;

enum Memory {
   B(1), KB(2), MB(3), GB(4), TB(5);
   public long val;

   private Memory(long val) {
      this.val = val;
   }
}

public class MemorySort {
   public static void main(String[] args) {
      List<String> memory = Arrays.asList("122003B",
            "1TB",
            "2KB",
            "100000MB",
            "1027MB",
            "2024GB");

      Comparator<String> units = Comparator.comparing(
            a -> Memory.valueOf(a.replaceAll("\\d+", "")).val);

      Comparator<String> values = Comparator.comparing(
            a -> Integer.parseInt(a.replaceAll("[A-Z]+", "")));

      Collections.sort(memory, units.thenComparing(values));
      System.out.println(memory);
   }
}



非常有帮助,但完全不是我需要的。简单来说,如果我有:1200MB、2MB、1GB,我希望它们按照以下顺序排序:2MB、1200MB、1GB。 - bfury
我修改了它以反映要求。虽然字符串替换仍不是很高效,但它能够正常工作。 - WJS

0
这可能会有用。 compare 方法获取每个字符串表示为 long 型的字节数(10KB 变成 10000),然后进行比较。 getSizeOfString 方法将一个字符串转换为代表它所表示的字节数的 long 型。
  public int compare(String o1, String o2) {
    long size1 = getSizeOfString(o1);
    long size2 = getSizeOfString(o2);
    return Long.compare(size1, size2);
  }

  private long getSizeOfString(String sizeString) {
    Pattern validSizePattern = Pattern.compile("(\\d+)([KMG])B");
    Matcher matcher = validSizePattern.matcher(sizeString);
    matcher.find();
    long size = Long.valueOf(matcher.group(1));

    switch (matcher.group(2)) {
      case "K":
        size *= 1024;
        break;
      case "M":
        size *= (1024 * 1024);
        break;
      case "G":
        size *= (1024 * 1024 * 1024);
        break;
    }
    return size;
  }

有帮助,但不是我想要做的事情。无需解析。如果我得到1001MB和1GB,我仍然需要以相同的顺序对它们进行排序。 - bfury
用这两个数字试一下,它会说1001MB比1GB多。这不是你要找的吗? - cheemcheem
解析只是让它们更容易进行比较,您还在寻找性能要求吗? - cheemcheem
不,我希望将1001MB视为小于1GB进行排序。 - bfury
但我认为您希望1025MB大于1GB。因此顺序应为1GB,1025MB。 - WJS
我将它们更改为使用KiB、MiB和GiB。这样它们现在会像1023MB < 1GB < 1025MB这样排序吗? - cheemcheem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接