文档章节

[转帖]字符串排序

穿越星辰
 穿越星辰
发布于 2010/05/13 21:11
字数 1624
阅读 77
收藏 0
原帖地址:
http://www.blogjava.net/jiangshachina/archive/2008/04/07/190912.html

本文是Sun官方以Blog形式发布的Java核心技术小窍门(JavaCoreTechTip)中的一个。我之前尚未关注过java.text.Collator类,看过Sorting Strings
这个tip之后觉得有些意义,故翻译在了此处,也希望对其它朋友有所助益。(2008.04.07最后更新)

    使用Java平台进行字符串排序被认为是一件简单的工作,但为国际 市场开发程序时,则需要有更多的考虑。如果你陷入只关注英语的心态中,并认为你的程序会工作的很好,因为它所显示的字符串从今往后都是一样的,你可能认为 一切都很正常。但一旦你有一位西班牙用户,他希望能够正常地对mañana进行排序,但如果你都是使用String类中缺省的compare方法去做排 序,字符ñ将会跟在字符z之后,而在正常的西班牙语排序中,ñ应该在字符n和o之间。这就是java.text包的类Collator发挥作用的地方了。
想像这样的一组词
  • first
  • mañana
  • man
  • many
  • maxi
  • next
使用String类的默认排序机制,即它的compare()方法,排序的结果将会是:
  • first
  • man
  • many
  • maxi
  • mañana
  • next
    此处,mañana出现在maxi与next之间。而在西班牙语世界中,mañana应该出现在many和maxi之间, 因为在字母表中,字符ñ(读作eñe)跟在n之后。当来了一个德语用户,想用他们自己的变音符时,你就可以写一个自己的定制排序规则来处理ñ, 否则一组使用façade的设计模式将会怎样呢?你是否想让façade出现在factory之前或之后呢?(关键是如同对c或其它字符那样去处理ç的小写变音符。)
    这就是类Collator能派上用场的地方了。类Collator用于对语言敏感的排序问题,并不会只基于它们的ASCII/Unicode字符去尝试排序。 使用Collator要求你在完全应用它的特性之前要理解一个额外的属性,即称之为强度(Strength)的属性。Collator的强度设置决定了在排序时如何使用强(或弱)匹配。 该属性有4个可能的值:PRIMARY,SECONDARY,TERTIARY和IDENTICAL。具体是哪个强度在产生作用取决于语言环境。 典型地,会有如下的情况。按从后往前的顺序,IDENTICAL强度表示能够被进行相同的处理的字符必须是一致的。TERTIARY通常用于忽略大小写差异。SECONDARY用于忽略变音符,如n和ñ。 PRIMARY与IDENTICAL相似也是基于字母之间差异,但是当处理控制字符和发音时还是有所不同。查看Collator的javadoc, 以获取更多关于这些强度之间的差异及分解(Decomposition)模式规则的信息。
    为了使用Collator,你需要先得到它的一个实例。你既可以调用getInstance方法以得到一个针对默认语言环境的Collator对象, 也可以传递一个指定的Locale对象给getInstance方法以得到一个针对特定语言环境的Collator对象。例如,为了获得针对一个西班牙语的 Collator对象,你应使用new Locale("es")去创建一个西班牙语的Locale对象,然后将它传入getInstance方法中:
<

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

> Collator esCollator  =
    Collator.getInstance(
new  Locale( " es " ));
    假设针对该语言环境的默认Collator强度,针对西班牙语的默认强度是SECONDARY已经足够了。然后你将这个Collator对象如任一Comparator对象 那样传入Collections类的sort方法的比较规则参数中,以得到排序后的List对象。
<

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

> Collections.sort(list, esCollator);
操作之前的单词列表,你现在就会得到一个基于西班牙语字母表的恰当排序结果:
  • first
  • man
  • many
  • mañana
  • maxi
  • next
如果你在上述Collator中换用US的Locale对象,由于ñ并不是US中本有的字母,所以mañana将会出现在man和many之间。
这儿有一个简洁的例子以显示这些差异。 import java.awt.*;
<

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

> import  java.text. * ;
import  java.util. * ;
import  java.util.List;  //  Explicit import required
import  javax.swing. * ;
public   class  Sort {
    
public   static   void  main(String args[]) {
        Runnable runner 
=   new  Runnable() {
            
public   void  run() {
                String words[] 
=  { " first " " mañana " " man " ,
                    
" many " " maxi " " next " };
                List list 
=  Arrays.asList(words);
                JFrame frame 
=   new  JFrame( " Sorting " );
                frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
                Box box 
=  Box.createVerticalBox();
                frame.setContentPane(box);
                JLabel label 
=   new  JLabel( " Word List: " );
                box.add(label);
                JTextArea textArea 
=   new  JTextArea( list.toString());
                box.add(textArea);
                Collections.sort(list);
                label 
=   new  JLabel( " Sorted Word List: " );
                box.add(label);
                textArea 
=   new  JTextArea(list.toString ());
                box.add(textArea);
                Collator esCollator 
=  Collator.getInstance( new  Locale( " es " ));
                Collections.sort(list, esCollator);
                label 
=   new  JLabel( " Collated Word List: " );
                box.add(label);
                textArea 
=   new  JTextArea(list.toString());
                box.add(textArea);
                frame.setSize(
400 200 );
                frame.setVisible(
true );
            }
        };
        EventQueue.invokeLater (runner);
    }
}

    最后还有一点儿关于语言排序规则的信息。通过调用getInstance方法而得到的Collator对象通常是支持特定语言的RuleBasedCollator实例。 你可使用RuleBasedCollator去定义你自己的排序顺序。该类的Javadoc更完整地描述了这种规则的语法,但还是让我们先假设你有一个4字符字母表, 并希望字母的顺序是CAFE,而不是ACEF,你的规则看起来就像这样:

<

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

> String rule  =
    
" < c, C < a, A < f, F < e, E " ;
RuleBasedCollator collator 
=   new  RuleBasedCollator(rule);
    上述规则通过展示不同字母的大小写定义了特定的字母顺序为cafe。现在对单词列表ace,cafe,ef和face使用新的规则进行排序, 排序结果的顺序为cafe,ace,face和ef:
<

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

> import  java.text. * ;
import  java.util. * ;

public   class  Rule {
    
public   static   void  main(String args[])  throws  ParseException {
        String words[] 
=  { " ace " " cafe " " ef " " face " };
        String rule 
= " < c, C < a, A < f, F < e, E " ;
        RuleBasedCollator collator 
=   new  RuleBasedCollator(rule);
        List list 
=  Arrays.asList(words);
        Collections.sort(list, collator);
        System.out.println(list);
    }
}
在对上述代码编译并运行之后,你将看到使用新规则排序后的单词:
<

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

> > javac Rule.java
> java Rule
[ cafe, ace, face, ef ]
    请以后再阅读Javadoc中关于 规则语法的更多内容,尝试扩展字母表并处理不同的变音符。
    现在,当你为全世界开发 程序时,你的程序就能做出更好的准备以去适应本地用户了。也要确保字符串在资源包中,如之前的一个窍门所展示的那样:Earlier tip。(译注:原文并没有提供这个Earlier tip的正确链接地址。)

本文转载自:http://www.jocoso.cn/lazygoo/diary/21201

上一篇: Html转义字符
下一篇: mysql两则
穿越星辰
粉丝 34
博文 162
码字总数 17996
作品 0
朝阳
技术主管
私信 提问
[算法研究]の快速排序算法--javascript实现

快速排序(Quicksort)是对冒泡排序的一种改进。 快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部...

FRED丶DON
2015/11/08
131
0
Collections 工具类和 Arrays 工具类常见方法

Collections 工具类和 Arrays 工具类常见方法 Collections 工具类和 Arrays 工具类常见方法 Collections Collections 工具类常用方法: 排序 查找,替换操作 同步控制(不推荐,需要线程安全的集...

小码哥的freestyle
04/16
0
0
[算法研究]の冒泡算法--javascript实现

很长时间没接触算法了,而且以前受某个老湿的误导,一直写的不是正规的冒泡排序,最近才发现,由于在做一些基础算法的了解,为了理清以下再巩固下冒泡算法: 冒泡排序算法的运作如下:(顺序...

FRED丶DON
2015/11/08
133
0
Razor:从aspx到cshtml常见错误及正确书写方法

从aspx转到chshtml还是有很多要适应的地方的,本帖是个人学习笔记帖不断更新。每天开着本帖编程。 按第一个有意义的编译错误的首字母排序,便于查找: Cannot implicitly convert type 'void...

wbf961127
2017/11/13
0
0
Python编程笔记 - 列表

这篇文章开始介绍Python中的容器。Python容器包括列表、元组、集合与字典。这些数据结构中都涉及到很多的方法,这里对比较常用的一些方法进行介绍,不用每个方法都记住,熟悉常用的即可。 首...

DemonFS
2018/01/17
9
0

没有更多内容

加载失败,请刷新页面

加载更多

前端技术之:Prisma Demo服务部署过程记录

安装前提条件: 1、已经安装了docker运行环境 2、以下命令执行记录发生在MackBook环境 3、已经安装了PostgreSQL(我使用的是11版本) 4、Node开发运行环境可以正常工作 首先需要通过Node包管...

popgis
今天
5
0
数组和链表

数组 链表 技巧一:掌握链表,想轻松写出正确的链表代码,需要理解指针获引用的含义: 对指针的理解,记住下面的这句话就可以了: 将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指...

code-ortaerc
今天
4
0
栈-链式(c/c++实现)

上次说“栈是在线性表演变而来的,线性表很自由,想往哪里插数据就往哪里插数据,想删哪数据就删哪数据...。但给线性表一些限制呢,就没那么自由了,把线性表的三边封起来就变成了栈,栈只能...

白客C
今天
43
0
Mybatis Plus service

/** * @author beth * @data 2019-10-20 23:34 */@RunWith(SpringRunner.class)@SpringBootTestpublic class ServiceTest { @Autowired private IUserInfoService iUserInfoS......

一个yuanbeth
今天
5
0
php7-internal 7 zval的操作

## 7.7 zval的操作 扩展中经常会用到各种类型的zval,PHP提供了很多宏用于不同类型zval的操作,尽管我们也可以自己操作zval,但这并不是一个好习惯,因为zval有很多其它用途的标识,如果自己...

冻结not
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部