Java 归类忽略空格

2022-09-02 22:27:49

我最近才意识到,Java Collation似乎忽略了空格。

我有以下术语的列表:

Amman Jost 
Ammann Heinrich 
Ammanner Josef 
Bär Walter 
Bare Werner 
Barr Burt 
Barraud Maurice

上面的顺序反映了德国所需的顺序,即占用空间进行计数。但是,Java 排序规则使用

Collator collator = Collator.getInstance(Locale.GERMANY);
Collections.sort(values, collator);

给我以下顺序:

Amman Jost
Ammanner Josef
Ammann Heinrich
Bare Werner
Barraud Maurice
Barr Burt
Bär Walter

上面的结果实际上不是我所期望的,因为空格没有被考虑在内(看起来像这里描述的情况:维基百科的字母顺序)。

这是否意味着,Java排序规则不适用于此类用例,或者我在这里做错了什么?有没有办法让Java归类空间感知?

我很乐意提出任何意见或建议。


答案 1

您可以自定义排序规则。请尝试查看源代码,了解如何构建德语区域设置的整理器,如本答案中所述。

然后根据您的需求进行调整。本教程给出了一个起点。但是不需要做所有的工作,其他人已经做到了:请参阅这篇博客文章,为捷克语处理完全相同的问题

上面链接的解决方案的本质是:

String rules = ((RuleBasedCollator) Collator.getInstance(Locale.GERMANY)).getRules();
RuleBasedCollator correctedCollator 
    = new RuleBasedCollator(rules.replaceAll("<'\u005f'", "<' '<'\u005f'"));

这将为下划线规则之前的空格字符添加一个规则。

我承认我没有亲自测试过这一点。


答案 2

如果您由于某些原因无法修改区域设置,那么我建议您自己编写所有内容。以下是一些想法,尽管此代码不完整且不起作用:

  • 与其列出字符串列表,不如创建自己的对象,实现可比较的对象:

    public class myString implements Comparable<myString> {
        private String name;
    
        public myString(String name) {
           this.name = name;
        }
    }
    
  • 然后,您将需要实现(请参阅此处的示例)

    public int compareTo(myString compareMyString) {
        ...
    }
    
  • 现在是更棘手的部分:

    • 为了比较字符串,您需要拆分它们(这将导致字符串数组)。例如:

      // Original String
      "Barr Burt"
      
      // Splitted String
      [0]: "Barr"
      [1]: "Burt"
      
    • 您将需要一个接一个地比较单词。创建一个执行类似操作的函数(这是一个伪代码:“this.words[i]”调用“this.name”的第i个单词)

      public int compareWords(myString compareMyString, int i)
      {
          if (this.words[i] < compareMyString.words[i])
              return -1; // "this" should come before "compareMyString"
      
          if (this.words[i] > compareMyString.words[i])
              return 1; // "this" should come after "compareMyString"
      
          if (this.words[i] == compareMyString.words[i])
              return compareWords(i+1);
      }
      
    • 然后:compareTo

      public int compareTo(myString compareMyString) {
          return compareWords(compareMyString, 0);
      }
      

推荐