Android切词工具——BreakIterator(1)
来源:互联网 发布:淘宝排名收费 编辑:程序博客网 时间:2024/06/07 07:01
本文介绍一下Android官方提供的切词工具BreakIterator。
1.关于切词
切词是一个常见的需求,对于中文更为重要,因为类似英文一样的以单词为中心的语言,以空格和标点符号为天然分隔符。但中文不一样,想要理解中文的准确含义,准确地切分词是第一步。例如,搜索的时候,如果输入是“看视频”,用户的意图显然是搜索视频,如果按照整句匹配,显然会欠召回。理想的情况应该是将“看视频”切成“看”和“视频”,并且识别出中心意图词是“视频”,进而主要搜索视频。当然,切词的准确性就很重要了,是一切的基础——如果切成“看视”和“频”,或者“看”“视”“频”,就适得其反了。
2.BreakIterator是个什么玩意?
Android官方SDK已经给出了切词工具BreakIterator,支持中文切词。目前Android SDK中同时存在两个BreakIterator:
java.text.BreakIterator
https://developer.android.com/reference/java/text/BreakIterator.html
android.icu.text.BreakIterator
https://developer.android.com/reference/android/icu/text/BreakIterator.html
前者API level 1,“根红苗正”。后者API level 24,从Android 7.0引入。其实二者同源。
二者用法基本相同,以前者为例,切一个句子,用法很简单友好:
public static void main(String args[]) { if (args.length == 1) { String stringToExamine = args[0]; //print each word in order BreakIterator boundary = BreakIterator.getWordInstance(); boundary.setText(stringToExamine); printEachForward(boundary, stringToExamine); } } public static void printEachForward(BreakIterator boundary, String source) { int start = boundary.first(); for (int end = boundary.next(); end != BreakIterator.DONE; start = end, end = boundary.next()) { System.out.println(source.substring(start,end)); } }
(1)ICU和android.icu.text.BreakIterator
什么是ICU?我们可以去官网看看:http://site.icu-project.org/ 。ICU - International Components for Unicode,这是一个处理国际化统一码(Unicode)的开源项目,提供大量的自然语言文本处理功能,切词只是其中之一。同时提供c/c++(ICU4C)和Java版本(ICU4J)。从官网上的这段话可以看出ICU的愿景是提供跨平台的统一编码和国际化能力:
ICU is a mature, widely used set of C/C++ and Java libraries providing Unicode and Globalization support for software applications. ICU is widely portable and gives applications the same results on all platforms and between C/C++ and Java software.
ICU目前最新的版本是59.1(20170414)。
android.icu.text,是Android 7.0将开源项目ICU引入了Android,并做了一些改进。android.icu.text.BreakIterator是其中一个重要的API。
(2)java.text.BreakIterator
从源代码看,java.text.BreakIterator是一个抽象类,由工厂方法getXXXInstance()提供实例:
Android 7.0以前:
/** * Returns a new instance of {@code BreakIterator} to iterate over * word-breaks using the default locale. * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". * @return a new instance of {@code BreakIterator} using the default locale. */ public static BreakIterator getWordInstance() { return getWordInstance(Locale.getDefault()); } /** * Returns a new instance of {@code BreakIterator} to iterate over * word-breaks using the given locale. */ public static BreakIterator getWordInstance(Locale locale) { return new IcuIteratorWrapper( com.ibm.icu.text.BreakIterator.getWordInstance(locale)); }
Android 7.0及以后:
/** * Returns a new <code>BreakIterator</code> instance * for <a href="#word">word breaks</a> * for the {@linkplain Locale#getDefault() default locale}. * * @return A break iterator for word breaks */ public static BreakIterator getWordInstance() { return getWordInstance(Locale.getDefault()); } /** * Returns a new <code>BreakIterator</code> instance * for <a href="#word">word breaks</a> * for the given locale. * * @param locale the desired locale * @return A break iterator for word breaks * @throws NullPointerException if <code>locale</code> is null */ public static BreakIterator getWordInstance(Locale locale) { return new IcuIteratorWrapper( android.icu.text.BreakIterator.getWordInstance(locale)); }
哈哈,原来java.text.BreakIterator也是封装了ICU。Android果然是开源大杂烩啊。
Android 7.0开始实际上直接用android.icu.text.BreakIterator了,两者就是一回事了。
Android 7.0以前,是引入的包com.ibm.icu.text,从Android codebase来看,android.icu.text.BreakIterator位于
external/icu/icu4j/main/classes/core/src/com/ibm/icu/text/BreakIterator.java
看到实际上icu是作为一个external库,作为Android源代码的一部分而存在。external/icu包含icu4j和icu4c。
3.中文切词效果测试
下面测试一下切词效果。我目前的应用场景在Android 6以及下,所以测试java.text.BreakIterator。测试环境Android 6.0.1,测试代码如下:
package com.example.testicu;import android.text.TextUtils;import java.text.BreakIterator;import java.util.ArrayList;public class Util { public static ArrayList<String> breakSentence(final String sentence) { final ArrayList<String> result = new ArrayList<String>(); if (!TextUtils.isEmpty(sentence)) { final BreakIterator boundary = BreakIterator.getWordInstance(); boundary.setText(sentence); try { int start = boundary.first(); for (int end = boundary.next(); end != BreakIterator.DONE; start = end, end = boundary.next()) { String word = sentence.substring(start, end); if (!TextUtils.isEmpty(word)) { result.add(word); } } } catch (IndexOutOfBoundsException e) { e.printStackTrace(); result.clear(); } } return result; }}
(1)常规词短语
可以看到常规词效果尚可。
(2)比较新的专用名词(以APP名为例)和人名
新词和人名基本无能为力。
(3)切句子效果如何
随便找一些中文句子来测试:
测试1:
杨振宁,1922年10月1日出生于安徽合肥,现任香港中文大学讲座教授、清华大学教授、美国纽约州立大学石溪分校荣休教授[1] ,是中国科学院院士、美国国家科学院院士、台湾“中央研究院”院士、俄罗斯科学院院士、英国皇家学会会员,1957年获诺贝尔物理学奖;是中美关系松动后回中国探访的第一位华裔科学家,积极推动中美文化交流和中美人民的互相了解;在促进中美两国建交、中美人才交流和科技合作等方面,做出了重大贡献。
结果1:
杨-振-宁-,-1922-年-10-月-1-日出生-于-安徽-合肥-,-现任-香港-中文-大学-讲座-教授-、-清华大学-教授-、-美国-纽约-州立-大学-石-溪-分校-荣-休-教授-[-1-]- - -,-是-中国-科-学院-院士-、-美国-国家-科-学院-院士-、-台湾-“-中央研究院-”-院士-、-俄罗斯-科-学院-院士-、-英国-皇家-学会-会员-,-1957-年-获-诺贝尔-物理-学-奖-;-是-中美关系-松-动-后-回-中国-探访-的-第-一位-华裔-科学-家-,-积极-推动-中美-文化-交流-和-中美-人民-的-互相-了解-;-在-促进-中美-两国-建交-、-中美-人才-交流-和-科技-合作-等-方面-,-做出-了-重大-贡献-。
测试2:
这首《飞鸟各投林》是《红楼梦》十二钗曲里的收尾曲,最早出现在第五回的时候,是以食尽鸟飞、唯余白地的悲凉图景,预示贾府未来子孙流散、十二钗花落断肠的惨象。当时林黛玉还未进大观园,这曲子就已为四大家族的衰亡预先敲起了丧钟。
结果2:
这-首-《-飞鸟-各-投-林-》-是-《-红楼梦-》-十二-钗-曲-里-的-收尾-曲-,-最早-出现-在-第五-回-的-时候-,-是以-食尽-鸟-飞-、-唯-余白-地-的-悲-凉-图-景-,-预示-贾-府-未来-子孙-流散-、-十二-钗-花落-断肠-的-惨-象-。-当时-林黛玉-还-未进-大-观-园-,-这-曲子-就-已-为-四大-家族-的-衰亡-预先-敲起-了-丧钟-。
测试3:
什么是ICU?我们可以去官网看看:http://site.icu-project.org/ 。ICU - International Components for Unicode,这是一个处理国际化统一码(Unicode)的开源项目,提供大量的自然语言文本处理功能,切词只是其中之一。同时提供c/c++(ICU4C)和Java版本(ICU4J)。从官网上的这段话可以看出ICU的愿景是提供跨平台的统一编码和国际化能力
结果3:
什么-是-ICU-?-我们-可以-去-官-网-看看-:-http-:-/-/-site.icu—project.org-/- -。-ICU- — -International- -Components- -for- -Unicode-,-这-是-一个-处理-国际-化-统一-码-(-Unicode-)-的-开-源-项目-,-提供-大量-的-自然-语言-文本-处理-功能-,-切-词-只是-其中-之一-。-同时-提供-c-/-c-+-+-(-ICU4C-)-和-Java-版本-(-ICU4J-)-。-从-官-网上-的-这-段-话-可以-看出-ICU-的-愿景-是-提供-跨-平台-的-统一-编码-和-国际-化-能力
可以看到对于长句子存在专用名词较差、切词过细的问题。
综合来看,对于常规的、短句子尚可一用。
- Android切词工具——BreakIterator(1)
- Android切词工具——BreakIterator(2)
- Android切词工具——BreakIterator(3)
- Android命令行工具(1)——draw9patch
- android 工具1 ——9-patch
- 第一章 工欲善其事 必先利其器—Android SDK工具(1)
- Android开发工具—ADB(Android Debug Bridge) 1 - 概览
- Android代码优化——使用Android lint工具(才发现这是个不错的工具)
- Android——工具对话框
- android日志工具—Log
- Android工具(1)——搭建安卓android应用开发环境
- Android UI 显示工具——HierarchyViewer工具
- Android被盗报案工具——ver0.1
- Android UI 优化(1)——使用HierarchyViewer工具
- Android命令行工具(2)——DDMS
- Android命令行工具(2)——DDMS
- Android自动化工具Monkeyrunner使用(六) —— touch
- Android系统开发(2)——GDB调试工具
- mysql 导入导出数据库
- 修改tomcat命令窗口的名字
- 第一次写博客,请多多关照!
- 如何学习好Javascript,需戒骄戒躁
- 如何做一个对账系统
- Android切词工具——BreakIterator(1)
- Jxl使用总结(转)
- ROHC报头压缩
- UnityShader案例(三)——BlinnPhong高光反射
- 音乐播放上一首,下一首
- GeoTools Eclipse 快速入门02
- 2017.06.14回顾 dtype相关 Series平均数 type_of_target
- Linux下使用NMON监控、分析系统性能
- 使用Apache的ab工具进行网站性能测试