17370845950

如何对字符串中成对的 ID-分数数据按分数升序排序

本文介绍如何将形如“1 456 2 100 3 600 1 400”的空格分隔字符串,按每对中的**分数值(而非id)升序重排**,并保持id与分数的绑定关系,最终输出格式一致的排序后字符串。

在处理这类“交替键值对”字符串时,直接按字符串或数字ID排序会导致逻辑错误(例如ID为1的两条记录被拆散或误排),关键在于语义建模:将每两个连续元素视为一个逻辑单元——即 id 和 score 组成的实体。因此,推荐采用面向对象方式封装数据,再借助Java集合的排序能力实现精准控制。

首先定义一个轻量级数据类:

public class Person {
    private final String id;
    private final int score;

    public Person(String id, int score) {
        this.id = id;
        this.score 

= score; } // 重写 toString() 以支持 "id score" 格式输出 @Override public String toString() { return id + " " + score; } }

接着解析原始字符串,按步长为2切分,并构建 Person 对象列表:

String input = "1 456 2 100 3 600 1 400";
String[] parts = input.split("\\s+"); // 使用正则处理多个空格更健壮

List people = new ArrayList<>();
for (int i = 0; i < parts.length; i += 2) {
    if (i + 1 >= parts.length) {
        throw new IllegalArgumentException("Invalid input: odd number of tokens");
    }
    String id = parts[i];
    int score = Integer.parseInt(parts[i + 1]);
    people.add(new Person(id, score));
}

然后使用 List.sort() 配合自定义比较器,按 score 升序排列(若需降序,可改为 Integer.compare(p2.score, p1.score)):

people.sort(Comparator.comparingInt(p -> p.score));

最后,将排序后的对象流式转换为字符串,用单个空格连接(注意:原题示例输出无逗号,因此应使用 " " 而非 ","):

String result = people.stream()
                      .map(Person::toString)
                      .collect(Collectors.joining(" "));
System.out.println(result); // 输出:2 100 1 400 1 456 3 600

注意事项

  • 不要使用 HashMap 存储,因ID可能重复(如本例中ID=1出现两次),会导致数据丢失;
  • 解析时务必校验数组长度为偶数,避免 ArrayIndexOutOfBoundsException;
  • 若输入含前导/尾随空格或多空格,split("\\s+") 比 split(" ") 更安全;
  • 如需稳定排序(相同分数时保持原始顺序),可改用 Collections.stableSort(...) 或在比较器中添加次级条件(如索引)。

该方案结构清晰、类型安全、易于扩展(例如后续增加姓名、时间戳等字段),是处理此类结构化字符串排序问题的标准实践。