IK Analyzer分词及词频统计Java简单实现

Stella981
• 阅读 1009

IK Analyzer基于Hadoop MapReducer框架Java实现:

1、新建一个ChineseWordCount类

2、在该类中再建一个私有静态类CWCMapper继承Mapper类,并复写Mapper类中map方法。

PS:Mapper的4个泛型分别为:输入key类型,通常为LongWritable,为偏移量;输入value类型;输出key类型;输出value类型

private static class CWCMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
        private final static IntWritable one = new IntWritable(1);
        private Text word = new Text();
        @Override
        protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
                throws IOException, InterruptedException {
            /**
            *要注意编码格式,本次红楼梦txt文档为GBK编码格式,则需要转换编码格式
            *转换编码格式,不能先将Text对象转换为String对象
            *转换不成功:String str=value.toString(); str=new String(str.getBytes(),"编码格式");
            应该直接value.getBytes(), 再转换格式*/
            byte[] bt = value.getBytes();
            //因为红楼梦的所有txt为gbk编码格式
            String str = new String(bt, "gbk");
            Reader read = new BufferedReader(new StringReader(str));
            IKSegmenter iks = new IKSegmenter(read, true);
            Lexeme t;
            while ((t = iks.next()) != null)
            {
                word.set(t.getLexemeText());
                context.write(word, one);
            }
        }
    }

3、同理,在该类中再建一个私有静态类CWCReducer继承Reducer类,并复写Reducer类中reduce方法。

private static class CWCReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
        @Override
        protected void reduce(Text value, Iterable datas,
                Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
              //value和datas的关系可以理解为(黛玉, list(1,1,1...)),即迭代datas即可以获取词频
              int sum = 0;
              for (IntWritable data : datas) {
                sum += data.get();
              }
              //写入文件乱码,是因为hadoop内部默认编码格式为utf-8, 则看输出文件的时候需要把编码调成utf-8
              context.write(value, new IntWritable(sum));
        }
    }

4、写main方法实现分词及词频统计

public static void main(String[] args) {
        try {
            Configuration cfg = HadoopCfg.getConfigration();
            Job job = Job.getInstance(cfg);
            job.setJobName("ChineseWordCount");
            job.setJarByClass(ChineseWordCount.class);
            job.setMapperClass(CWCMapper.class);
            job.setMapOutputKeyClass(Text.class);
            job.setMapOutputValueClass(IntWritable.class);
            job.setReducerClass(CWCReducer.class);
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(IntWritable.class);
            FileInputFormat.addInputPath(job, new Path("/hongloumeng"));
            FileOutputFormat.setOutputPath(job, new Path("/hongloumengCount/"));
            System.exit(job.waitForCompletion(true) ? 0 : 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

5、最后可以利用java对输出文件做处理,取词语出现频率最高的前50个,丢掉我,你,他,的等词

public class SortWords {
    private static final int NUM=200;
    
    public static void main(String[] args) {
        try {
            BufferedReader br = new BufferedReader(new FileReader(new File("hong-words.txt")));
            Map<String, Integer> map = new HashMap<String, Integer>();
            String line = br.readLine();
            while(!"".equals(line) && line!=null){
                String[] strs = line.split("    ");

                if(strs[0].length()<2){
                    line = br.readLine();
                    continue;
                }else{
                    map.put(strs[0], Integer.parseInt(strs[1]));
                    line = br.readLine();
                }
            }
            List<Map.Entry<String, Integer>> list = 
                    new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
            Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {

                public int compare(Entry<String, Integer> o1,
                        Entry<String, Integer> o2) {
                    return o1.getValue()-o2.getValue();
                }
            });
            BufferedWriter bw = new BufferedWriter(new FileWriter(new File("hong-words2.txt")));

            if(list!=null){
                for(int i=list.size()-1; i>=list.size()-NUM; i--){
                    bw.write(list.get(i).toString()+"\n");
                }
            }
            br.close();
            bw.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

结果展示:

宝玉=14181
笑道=8841
听了=4422
黛玉=4313
我们=4248
一个=4113
宝钗=4075
去了=4031
凤姐=3930
如今=3890
什么=3846
你们=3734
姑娘=3470
王夫人=3447
众人=3375
他们=3290
说道=3261
那里=3228
来了=3126
一面=3111
奶奶=2977
太太=2929
自己=2817
袭人=2804
老太太=2650
不知=2578
这样=2565
这个=2548
老爷=2452
只见=2434
出来=2351
两个=2296
咱们=2244
这里=2175
湘云=2169
怎么=2136
起来=2128
大家=2122
丫头=2106
只是=2087
所以=1980
也是=1945
知道=1930
姐姐=1918
姨妈=1854
告诉=1803
不是=1769
这些=1756
的人=1731
只得=1730

写在最后:本人初次接触Hadoop及IK Analyzer分词工具,若有不正确的地方,望多多指教!下次将更新jieba分词Python实现。

分享:http://my.oschina.net/apdplat/blog/412921?fromerr=bQjYmVTB

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java8新特性
Stream将List转换为Map,使用Collectors.toMap方法进行转换背景:User类,类中分别有id,name,age三个属性。List集合,userList,存储User对象1、指定keyvalue,value是对象中的某个属性值。 Map<Integer,StringuserMap1userList.str
Stella981 Stella981
3年前
Jieba分词Python简单实现
上一章分享了IKAnalyzer中文分词及词频统计基于Hadoop的MapReducer框架Java实现。这次将与大家分享Jieba中文分词Python简单实现,由于Jieba分词是基于词频最大切分组合,所以不用做词频统计,可以直接得到其关键字。1、安装jieba安装方式可以查看博主的中文分词工具(http://my.oschina.net/ea
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这