【译自:http://tutorials.jenkov.com/java-internationalization/breakiterator.html , 不准确别怪我】
java.text.BreakIterator
类用来查找不同语言中的字符、单词和句子的边界。因为不同的语言有不同的字、单词和句子的边界,所以只是查找空格、逗号、句号、分号和冒号是不够的。你需要一个万无一失的、可用于各种语言的查找方法。BreakIterator
类就是干这个的。
创建一个 BreakIterator
一个 BreakIterator
实例只能判断以下四种边界之一:
- 字符边界
- 单词边界
- 句子边界
- 行边界
首先需要使用BreakIterator类提供的用于识别以上边界的,对应的工厂方法来创建一个实例。这些工厂方法有:
BreakIterator.getCharacterInstance();
BreakIterator.getWordInstance();
BreakIterator.getSentenceInstance();
BreakIterator.getLineInstance();
每个方法都需要一个 Locale
作为参数,然后返回一个 BreakIterator
实例,例如:
Locale locale = LocaleUK;
BreakIterator breakIterator =
BreakIterator.characterInstance(locale);
字符边界
当查找一个字符边界时,需要区分用户字符和Unicode字符。
一个用户字符是指用户用笔书写时或者用户通常在屏幕上看到了字符。
一个用户字符通常需要一个或多个Unicode字符去表示;有的需要2个或更多的Unicode字符来表示。
一个 BreakIterator
的字符实例可以用于查找用户字符的边界,而不是Unicode字符。
例如,以下例子用来查找一个字符串的字符边界:
Locale locale = Locale.UK;
BreakIterator breakIterator =
BreakIterator.getCharacterInstance(locale);
breakIterator.setText("Mary had a little Android device.");
int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
System.out.println(boundaryIndex) ;
boundaryIndex = breakIterator.next();
}
上例创建了一个用于英式英语的 BreakIterator
实例,然后调用setText()
方法指定用于查找的文本内容。
first()
方法返回找到的第一个断点,方法 next()
用于查找所有接下来的断点。这两个方法都返回查找到的用户字符中的Unicode字符索引。因此,如果一个用户字符占用了多于一个的Unicode字符,那么字符的索引会增加占用的Unicode字符数。
单词边界
当查找单词时,需要创建一个符合单词边界的、针对特定语言的BreakIterator
实例,下面是一个示例:
Locale locale = Locale.UK;
BreakIterator breakIterator =
BreakIterator.getWordInstance(locale);
以上代码创建一个用于查找英国英语中单词边界的
BreakIterator
实例。
下面的例子演示了怎么查找一段英语文本的单词边界:
Locale locale = Locale.UK;
BreakIterator breakIterator =
BreakIterator.getWordInstance(locale);
breakIterator.setText("Mary had a little Android device.");
int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
System.out.println(boundaryIndex) ;
boundaryIndex = breakIterator.next();
}
同样的,first()
和 next()
方法返回查找到单词的Unicode字符的索引。
用Java统计特定语言中的单词数Counting Words in a Specific Language in Java
这个Java代码片段显示了如果统计某个特定语言中的单词数:
public class WordCounter {
public static class WordCount {
protected String word = null;
protected int count = 0;
}
public static Map<String, WordCount> countWords(String text, Locale locale) {
Map<String, WordCount> wordCounts = new HashMap<String, WordCount>();
BreakIterator breakIterator = BreakIterator.getWordInstance(locale) ;
breakIterator.setText(text);
int wordBoundaryIndex = breakIterator.first();
int prevIndex = 0;
while(wordBoundaryIndex != BreakIterator.DONE){
String word = text.substring(prevIndex, wordBoundaryIndex).toLowerCase();
if(isWord(word)) {
WordCount wordCount = wordCounts.get(word);
if(wordCount == null) {
wordCount = new WordCount();
wordCount.word = word;
}
wordCount.count++;
wordCounts.put(word, wordCount);
}
prevIndex = wordBoundaryIndex;
wordBoundaryIndex = breakIterator.next();
}
return wordCounts;
}
private static boolean isWord(String word) {
if(word.length() == 1){
return Character.isLetterOrDigit(word.charAt(0));
}
return !"".equals(word.trim());
}
}
方法countWords()
需要一个 string 参数和一个 Locale
参数。Locale
代码了传入的string的语言类别。因此,当创建 BreakIterator
,它可以创建针对那个语言类型的实例。
这个方法统计了一个单词在传入的串中有多少个,然后返回一个 Map<String, WordCount>
对象,Map中的key是一个一个单词,以小写形式表示,值是一个 WordCount
实例,它包含了两个变量:word
和 count
。只需要把所有的单词发生的次数相加就可以得到总的单词数了。
注意:isWord()
方法中是怎么使用 Character.isLetterOrDigit()
方法来判断某个字符是字母还是数字的,或者是其他的(例如分号,引号等)。Character.isLetterOrDigit()方法检查对应的
unicode characters 是字母还是数字,并且不仅仅用在英语上,也可以用于其他语言。关于这个方法和其他的一些类似的方法的更详细的描述,可以参考:Characeter Methods 。
句子边界
对于特定语言的句子边界,需要创建一个BreakIterator
针对那种语言的句子边界实例:
Locale locale = Locale.UK;
BreakIterator breakIterator =
BreakIterator.getSentenceInstance(locale);
以上代码创建了一个针对英国英语的
BreakIterator
句子实例。
以下示例查找英语文本中的句子边界:
Locale locale = Locale.UK;
BreakIterator breakIterator =
BreakIterator.getSentenceInstance(locale);
breakIterator.setText(
"Mary had a little Android device. " +
"It had small batteries too.");
int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
System.out.println(boundaryIndex) ;
boundaryIndex = breakIterator.next();
}
行边界
也可以查找某段文本中的新行而不中断文本的阅读。这个时候需要一个拥有用于侦探潜在的行边界的BreakIterator
实例。注意:这并不能找到直接的行断点,而是潜在的行断点。找到潜在的行中断是需要把文本划分成多行显示的时候相当有用,即使这段文本不包括任何显示的分行。以下是一个创建这个的 BreakIterator
实例的例子:
Locale locale = Locale.UK;
BreakIterator breakIterator =
BreakIterator.getLineInstance(locale);
这个例子创建一个拥有英式英语的潜在的行分割通用的 BreakIterator
实例。
下面的例子用于查找潜在的行分割:
Locale locale = Locale.UK;
BreakIterator breakIterator =
BreakIterator.getLineInstance(locale);
breakIterator.setText(
"Mary had a little Android device.\n " +
"It had small batteries too.");
int boundaryIndex = breakIterator.first();
while(boundaryIndex != BreakIterator.DONE) {
System.out.println(boundaryIndex) ;
boundaryIndex = breakIterator.next();
}