大数据Mapreduce程序——词频统计修改

思路原理介绍

在开始学习Mapreduce程序编写时,通常第一个程序为词频统计。词频统计,顾名思义是统计一篇文档中不同词出现的频数。而本文是在基本词频统计mapreduce程序的基础上进行改进。
在本次实验中,利用mapreduce自带的框架,将每个单词切片,将其设为key,value的值初始为“+”。通过Partitione计算分区,在Combine中将单词的value追加“+”,将其词频增加1倍,最后在Reduce中统计每个单词的词频,并将词频大于或等于3的单词记录,最终输出2倍词频数量的“+”组成的字符串。

改进要求

在实现基本的词频统计的功能基础上,对程序进行以下修改:

  1. 数据清洗: 对每个词的格式进行规范化(去除不以英文字母开头的所有词)词频小于3次的数据不在结果中显示;
  2. 结果以有限数量的“+”表示词频统计;
  3. 自定义一个Combiner类,在其reduce方法中,将相同key的所有值进行相加后乘以2输出;
  4. 自定义一个Partitioner类和getPartition()方法,将大写字母开头的词分配到一个reducer,将小写字母开头的词分配到另一个reducer;

环境

hadoop:2.9.2

步骤

  1. 生成键值对:在框架中的map 方法中,读取文档中每个单词,判断其是否以大小写字母开头,若符合条件,将其设为key,且其value为“+”;否则丢弃,不处理。通过该方法,得到键值对的列表。
  2. 计算分区:在myPartitioner方法中,获取键值对key的值,如果key是大写字母开头,将其分配到属于“0”的reduce中,否则分配到为“1”的reduce中。
  3. 增加单词的频数:在MyCombiner方法中,获取每个键值对中的value,并将其增加为原来的两倍,并更新原来的value。
  4. 在IntSumReducer方法中,定义一个StringBuffer类型的sum,统计相同key的键值对,将其value值追加到sum中,最终sum的值为该单词频数的两倍,且sum是以有限个“+”组成的字符串。最后判断sum的长度是否大于或等于6,若满足,则将词频大于3的单词及其sum结果加入到结果集中;否则,丢弃,不记录。

注意:由于在初始化词频时,将初始值设置为2,因此,在后续中过滤词频小于3的词时,过滤的条件修改为小于6.

代码

map部分

从文件中读取每一个词,并检查该词是否为大小写字母开头

    private final static Text one = new Text("+");
    private Text word = new Text();

    public void map(LongWritable key, Text value, Context context
                    ) throws IOException, InterruptedException {
      
    //筛选以字母开头的单词
	   StringTokenizer itr = new StringTokenizer(value.toString());
	   while (itr.hasMoreTokens()) {
		String line = itr.nextToken().toString();
			//****itr.nextToken()为string 类型;String line = itr.nextToken()
	                if((line.charAt(0) >= 65 && line.charAt(0) <= 90) || (line.charAt(0) >= 97 && line.charAt(0) <= 122)){
			//  ****使用正则表达式,条件可写为:line.substring(0,1).toLowerCase().matches("[a-z]")
		   word.set(line);
		   context.write(word, one);
		}
	   }
    }

Combiner片段

public static class MyCombiner extends Reducer<Text,Text,Text,Text> {
	    private Text result = new Text();

	    public void reduce(Text key, Iterable<Text> values,
		               Context context
		               ) throws IOException, InterruptedException {
	      StringBuffer sum = new StringBuffer();
	      for (Text val : values) {
		sum.append(val.toString());
	      }
	      result.set(sum.append(sum).toString());
	      context.write(key, result);
	    }
  }

Partitioner

在partitioner部分,设置分区方式

public class myPartitioner extends Partitioner<Text,Text>{
  	public int getPartition(Text key, Text value, int numPartitions)
	{
	     String line = key.toString(); 
             if(line.charAt(0) >= 65 && line.charAt(0) <= 90){
		return 0;
             }
	     return 1;
	}
  }

reducer

public static class IntSumReducer
       extends Reducer<Text, Text, Text, Text> {
    private Text result = new Text();

    public void reduce(Text key, Iterable<Text> values,
                       Context context
                       ) throws IOException, InterruptedException {
      StringBuffer sum = new StringBuffer();
      for (Text val : values) {
        sum.append(val.toString());
      }
      // 只统计词频>=3的单词
      if(sum.length() >= 3){
        result.set(sum.toString());
      	context.write(key, result);
      }
    }
  }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值