MapReduce入门之多种统计方式wordcount(续)

这次的学习是在MapReduce入门之后的,上次实现了简单的单词统计的计算,是对文件全部的读取划分。本次学习多种读取和划分方式。

在读取的时候,单独读取第二个位置的单词进行统计


只需要将上次的MyMapper程序进行修改,修改情况如下:

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class MyMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
    protected void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException
    {
        String[] str = value.toString().split(" ");
        //现在只统计第二个单词
        ontext.write(new Text(str[1]),new IntWritable(1));
        //原来全部统计
        //context.write(new Text(ss),new IntWritable(1));   
    }
}
统计两个位置的单词数量——Partitionr类的应用


首先在wordcount类中需要再加Partition的设置。

job.setNumReduceTasks(2);//此处的二为读取两个位置的单词数量。
job.setPartitionerClass(MyPartitioner.class);


MyMapper类:

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class MyMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
    @Override
    protected void map(LongWritable key,Text value,Context context) throws IOException, InterruptedException
    {
            Text ss = new Text();
            ss.clear();
            //使用不同的前缀标记
            ss.set(new StringBuffer("loglevel::").append(str[1]).toString());
            context.write(new Text(str[1]), new IntWritable(1));
            //同一个Text对象,在读取完毕后再次读取之前需要clear。
            ss.clear();
            ss.set(new StringBuffer("loglevel::").append(str[2]).toString());
            context.write(new Text(str[2]), new IntWritable(1));
    }
}


MyReduce类不需要更改,新建一个MyPartitioner类

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;

public class MyPartitioner extends Partitioner<Text, IntWritable>{
@Override
public int getPartition(Text key, IntWritable value, int arg2) {
    //参数三arg2:就是在wordcount类中设置的参数job.setNumReduceTasks(2);
    if(key.toString().startsWith("loglevel::"))
            return 0;//分发到第一个reducer
    else if(key.toString().startsWith("logresource::"))
            return 1;//分发到第二个reducer    0,1要以次写出来
        return 0;
        }
}

如此就可以实现对一个文档的两处进行读取,分别输出到两个文件,及本次的输出目录中会有三个文件。

combiner的使用

combiner实为Reduce前的数据处理类。
①每一个Map可能会产生大量的输出,Combiner的作用就是在Map端对输出先做一次合并,以减少传输到reducer的数据量。
②Combiner最基本是实现本地key的归并,Combiner具有类似本地的Reduce功能。
如果不用Combiner,那么,所有的结果都是reduce完成,效率会相对低下。
使用Combiner,先完成的map会在本地聚合,提升速度。
注意:Combiner的输出是Reducer的输入,如果Combiner是可插拔的,添加Combiner绝不能改变最终的计算结果。所以Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。

InputFormat的自我实现


总体流程如下:
(1) 在wordcount中写入job.setInputFormat(MyInputFormat.class)
(2) 新建MyInputFormat.class 类(继承FileInputFormat,FileInputFormat继承InputFormat)重写两个方法:getSplits 方法不需要改动 和 createRecordReader 的返回值类型修改为:(return new Myrecordreader())
(3) 新建Myrecordreader类,继承RecordReader类型改为这个:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值