在Java中对多语言环境字符串进行排序

我正在尝试按字符串字段“country”对对象列表进行排序。 每个国家都使用其母语

  • 阿根廷
  • 澳大利亚
  • Österreich
  • Ελλάδα
  • България…

我想做的是让“България”例如出现在“A *”国家之后,因为字母’Б’对应于拉丁’B’。 我正在尝试使用默认的Collat​​er,但非拉丁名称仍然在列表中排在最后。

到目前为止,这是我的代码:

private static final Comparator DOMAIN_COUNTRY_COMPARATOR = new Comparator() { @Override public int compare(DomainTO t, DomainTO t1) { Collator defaultCollator = Collator.getInstance(); return defaultCollator.compare(t.getCountry(), t1.getCountry()); } }; 

如何对不同语言的单词进行排序? 有许多字母表(英语,俄语,德语等)。 每个人都订购了一系列信件。 对来自一个字母表的单词进行排序很容易。 但是有可能将所有这些字母合并成一个吗?
我认为不可能以一种可以被所有人接受的方式来实现。 以英语和俄语字母为例。 俄语字母可以转换成英文字母(至少大部分都是),但是在这个演员之后他们会改变顺序。 这将有利于一个字母表而不是另一个字母表。 为什么不给俄语写英文字母?
另一个问题是有特殊字母。 在德语中,O和P之间有Ö,波兰语中有Ó在这个地方。 所以我们有以下关系:

 O < Ö < PO < Ó < P 

但Ö和Ó之间的关系是什么? 如果有一个国家Ósterreich应该是或Österreich之后? 因此,不可能定义从不同语言中排序单词的通用规则。

我们所能做的就是将所有字母表投射到所选字母表中。 这就是OP正在尝试做的事情。
所选择的是拉丁字母表,其他字母表必须输入到此字母表中。 问题是这种铸造通常是模棱两可的。 很容易我们只能投出大部分俄语或希腊字母。
更大的问题是阿拉伯语或亚洲语言。 我们应该记住,当从一个字母表转换到另一个字母表时,我们经常会丢失一些

那我们怎么做这样的排序呢?

  1. 第一个主张是为每个国家手动提供拉丁名称。 所以我们会有一个包含对的列表
    • РоссияRossija
    • ΕλλάδαEllada
      然后我们可以按拉丁名称和显示名称排序。
  2. 第二种方法是运行类似于此的代码:

码:

 char [] russian = "АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщ".toCharArray(); char [] russian_to = "AaBbWwGgDdEeEeZzZzIiJjKkLlMmNnOoPpRrSsTtUuFfHhCcCcSsss".toCharArray(); for (int i = 0; i < russian.length; i++) { input = input.replace(russian[i], russian_to[i]); } 

这样我们就转换了俄语字母表中的所有字母。 现在我们必须为其他字母添加类似的代码。 而俄语是最简单的。
但是假设我们成功了,我们设法对世界上所有语言进行了这样的排序。
但是进行这种分类的后果是什么? 在我们回答这个问题之前,让我们问一下这样做的目的是什么。 OP没有说他做这种排序的原因。 但我们可以推断它:

  • 我们为什么要对元素进行排序?:为了使它们更容易找到。
  • 为什么国家的名称是用母语?:为了使这个列表对世界上只懂母语的公民有用。

那么让我们回答这个问题:这种排序是否更容易找到只知道他的母语的人?

  1. 如果有人来自奥地利,那么他认为Österreich将在所有以O开头的国家之后。但在正常化之后,Österreich将成为Osterreich并且将介于安大略省和渥太华之间。 (我知道安大略省和渥太华不是国家。这只是一个例子)。
  2. 如果有人来自日本并且不懂拉丁字母,那么这种排序对他来说是无用的。 他必须扫描所有列表,直到找到他的国家。
  3. 假设有国家Волгоград(Wolgograd)并且有只知道俄语字母的这个国家的市民。 在俄语字母表中В是第三个字母,因此当Волгоград接近列表的末尾(靠近委内瑞拉)时,这个人会在列表的开头(比利时和丹麦之间的某个地方)搜索。 所以在这种情况下,排序不仅没有帮助,而且还具有误导性。
  4. 如果有人知道拉丁字母并正在搜索他的国家,那么这并不容易。 当所有国家都以英文命名并且我正在寻找“波兰”时,我总是知道我是否应该在列表中上下。 如果我看到“日本”,我知道要列入清单。 当我看到'俄罗斯'然后我知道要上去。
    但如果我们对所有这些名称进行排序,那么可能会出现问题。 如果我看到了ايران,那么我将无法决定是否上下列表。 所以在这个例子中,排序没有帮助。 更糟糕的情况是我在名单上遇到Волгоград。 我不知道俄语字母,我会认为我接近'B'字母,实际上我接近列表的末尾。 然后我会选择错误的方向。

摘要:

对以不同语言编写的国家/地区名称进行排序很难定义和实施。 并且当实施时,它将是无用的或有害的。

也许你可以比较规范化的字符串。 像这样的东西:

 private static final Comparator DOMAIN_COUNTRY_COMPARATOR = new Comparator() { private String normalize(final String input) { return Normalizer .normalize(input, Normalizer.Form.NFD) .replaceAll("[^\\p{ASCII}]", ""); } @Override public int compare(final DomainTO t, final DomainTO t1) { return normalize(t.getCountry()).compareTo( normalize(t1.getCountry())); } }; 

请参阅有关规范化的相关问题: 将Java字符串转换为ascii (此问题与几个类似的问题相关联)