【问题标题】:Java collation ignores spaceJava 排序规则忽略空格
【发布时间】:2013-05-10 03:46:12
【问题描述】:

我最近意识到,Java 排序规则似乎忽略了空格。

我有以下术语的列表:

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

上面的结果实际上不是我所期望的,因为没有考虑空格(看起来像这里描述的情况:Wikipedia Alphabetical order)。

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

如果有任何 cmets 或建议,我会很高兴。

【问题讨论】:

标签: java collation


【解决方案1】:

您可以自定义排序规则。尝试查看源代码以了解如何构建德语语言环境的 Collat​​or,如 this answer 中所述。

然后根据您的需要进行调整。 tutorial 给出了一个起点。但无需完成所有工作,其他人已经完成了:请参阅blog post dealing with the exact same problem for Czech

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

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

这会在下划线规则之前添加一个空格字符规则。

我承认我没有亲自测试过。

【讨论】:

  • 感谢您的回答和有用的链接。更大的问题是,对于应该按用户区域设置进行整理的基于 Web 的应用程序,可能需要增强许多区域设置。
  • 那你自己写吧:看看我下面的提议能不能帮到你
  • @jhasenbe 是的,这并不令人满意。您可能会破解某些东西以在具有类似规则的任何语言环境上执行相同的更改,但这将是一个 hack
【解决方案2】:

如果由于某些原因您无法修改语言环境,那么我建议您自己编写所有内容。这里有一些想法,虽然这段代码不完整并且不起作用:

  • 创建自己的对象,而不是字符串列表,实现可比较:

    public class myString implements Comparable<myString> {
        private String name;
    
        public myString(String name) {
           this.name = name;
        }
    }
    
  • 然后你需要实现(见例子here

    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);
      }
      

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-18
    • 2012-04-30
    • 2019-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    相关资源
    最近更新 更多