MapReduce求WordCount实验(流程+代码)

实验:分析和编写 WordCount 程序

原始数据:

a good beginning is half the battle

where there is a will there is a way

思路:读取文件,采用 TextInputformat 读取每一行数据,切割得到每一个单词,进行 map,reduce 后得到每个单词出现的次数,可使用 Combiner。

Map阶段:k1 为文本偏移值,v1 为每行的数据,进行切割,得到 k2 为每个单词。V2 都为 1,然后写到上下文对象中。
Shuffle阶段:这里使用了规约,以减少网络传输量(和 reduce 代码一样),分区、排序、分组采用系统默认。
Reduce阶段:shuffle 后得到新的 k2 和 v2,此时 v2 是一个集合,元素都是1,对他相加就可以得到对应单词出现的次数,即 v3,而 k3 和新的 k2 是一样的。

流程图

结果:
没有使用 Combiner

使用 Combiner


可以看到使用规约后,map 后的 <k2,v2> 进行网络传输少了一些,以减少网络开销,当然只有在不改变结果的逻辑才能规约。

输出结果

其他 MapReduce 实验:

薪水分区实验

职位和薪水序列化排序实验

求各年销售笔数、销售总额实验


本次实验的代码

Map代码:

package lhr.word_count.homework;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;

public class word_count_Mapper extends Mapper<LongWritable, Text, Text, LongWritable> {
    
    
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    
    
        /*
            map阶段:
                   首先将读取到的每一行以空格进行切割得到每个单词,
                   再将每个单词写到上下文对象,即<k2,v2>,k2的值为每个单词,v2的值为1。
         */
        String[] s = value.toString().split(" ");
        for (String s1 : s) {
    
    
            context.write(new Text(s1), new LongWritable(1));
        }
    }
}

Combiner代码:

package lhr.word_count.homework;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class word_count_combiner extends Reducer<Text, LongWritable, Text, LongWritable> {
    
    
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
    
    
        long word_counts = 0;
        for (LongWritable value : values) {
    
    
            word_counts += value.get();
        }
        context.write(key, new LongWritable(word_counts));
    }
}

Reduce代码:

package lhr.word_count.homework;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;

public class word_count_Reducer extends Reducer<Text, LongWritable, Text, LongWritable> {
    
    
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
    
    
        /*
            reduce阶段:
                        对shuffle网络传输(分区、排序、规约、分组)过来的新k2,v2进行统计,
                        将v2中每个1相加,得到该单词出现的次数。
         */
        long word_counts = 0;
        for (LongWritable value : values) {
    
    
            word_counts += value.get();
        }
        context.write(key, new LongWritable(word_counts));
    }
}

Main代码:

package lhr.word_count.homework;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import java.net.URI;

public class word_count_Main extends Configured implements Tool {
    
    
    //指定job任务
    @Override
    public int run(String[] strings) throws Exception {
    
    
        //2:配置job任务对象
        Job job = Job.getInstance(super.getConf(), "word_count");

        //指定jar包主类
        job.setJarByClass(word_count_Main.class);

        //采用默认的类一行一行读取文件内容
        job.setInputFormatClass(TextInputFormat.class);

        //指定读取文件的地址,可以本地,也可以集群
//        TextInputFormat.addInputPath(job, new Path("hdfs://hadoop11:8020/word_count"));
        TextInputFormat.addInputPath(job, new Path("file:///D:\\input0"));

        //指定Map阶段的处理方式和数据类型
        job.setMapperClass(word_count_Mapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        //规约,减少网络传输
        job.setCombinerClass(word_count_combiner.class);

        //指定Reduce阶段的处理方式和数据类型
        job.setReducerClass(word_count_Reducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        //采用默认的类一行一行存文件内容
        job.setOutputFormatClass(TextOutputFormat.class);

        //指定输出结果文件的地址,可以本地,也可以集群
//        Path path = new Path("hdfs://hadoop11:8020/word_count_result");
        Path path = new Path("file:///D:\\output0");
        TextOutputFormat.setOutputPath(job, path);

        //如果集群输出结果文件存在,删除,方便下次运行
//        FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop11:8020"), super.getConf(), "root");
//        if (fileSystem.exists(path)) {
    
    
//            fileSystem.delete(path, true);
//        }

        //等待任务结束
        boolean b = job.waitForCompletion(true);
        return b ? 0 : 1;
    }

    public static void main(String[] args) throws Exception {
    
    
        Configuration configuration = new Configuration();

        //启动job任务
        int run = ToolRunner.run(configuration, new word_count_Main(), args);
        System.exit(run);
    }
}

猜你喜欢

转载自blog.csdn.net/lhrfighting/article/details/118208581