MapReduce实例WordCount的编程实现与Hadoop数据类型介绍

8 篇文章 0 订阅
7 篇文章 0 订阅

Hadoop数据类型介绍

我们知道hadoop是由Java 编程写的。因此我们使用Java开发环境来操作HDFS,编写mapreduce也是很自然的事情。但是这里面hadoop却对Java数据类型进行了,那么hadoop的数据类型与Java那些数据类型对应。下面做一些对比:

(1) 在hadoop.io包,主要分为基本类型和其它类型。

(2) 基本类型:

数据类型hadoop数据类型Java数据类型
布尔型*BooleanWritableboolean
整型*IntWritableint
浮点float*FloatWritablefloat
浮点型*DoubleWritabledouble
整数类型byte*ByteWritablebyte
String*TextString
数组ArrayWritablejava数组

这里说明一下,hadoop类型与Java数据类型之间如何转换:
有两种方式
1.通过set方式
2.通过new的方式。

WordCount编程实现

hadoop v3.1.3

  1. 前提需要导入的jar包:
    目录/usr/local/hadoop/share/hadoop/中
    common文件夹的所有,MapReduce文件夹的所有。
    还需要特别导入一个common/lib/commons-cli-1.2.jar,否则会报错哦

  2. 下面给出完整的WordCount代码:

个别代码解释:

  1. Context是Mapper的内部类,为了在map或reduce任务中跟踪task的状态,MapContext记录map执行的上下文,同时context也是map和reduce执行的各个函数的桥梁,与session对象相似
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

//启动mr的driver类
public class WordCount {

    //map类,实现map函数
    public static class TokenizerMapper extends
            Mapper<Object, Text, Text, IntWritable> {
        //暂存每个传过来的词频计数,均为1,省掉重复申请空间
        private final static IntWritable one = new IntWritable(1);
        //暂存每个传过来的词的值,省掉重复申请空间
        private Text word = new Text();

        //核心map方法的具体实现,逐个<key,value>对去处理. 在词频统计操作中,value是文本中的一行,key是文本中的行号
        public void map(Object key, Text value, Context context)
                throws IOException, InterruptedException {
            //用每行的字符串值初始化StringTokenizer
            StringTokenizer itr = new StringTokenizer(value.toString());
            //循环取得每个空白符分隔出来的每个元素(单词)
            while (itr.hasMoreTokens()) {
                //将取得出的每个元素放到word Text对象中
                word.set(itr.nextToken());
                //通过context对象,将map的输出逐个输出
                context.write(word, one);
            }
        }
    }

    //reduce类,实现reduce函数
    public static class IntSumReducer extends
            Reducer<Text, IntWritable, Text, IntWritable> {
        private IntWritable result = new IntWritable();

        //核心reduce方法的具体实现,逐个<key,List(v1,v2)>去处理
        public void reduce(Text key, Iterable<IntWritable> values,
                           Context context) throws IOException, InterruptedException {
            //暂存每个key组中计算总和
            int sum = 0;
            //加强型for,依次获取迭代器中的每个元素值,即为一个一个的词频数值
            for (IntWritable val : values) {
                //将key组中的每个词频数值sum到一起
                sum += val.get();
            }
            //将该key组sum完成的值放到result IntWritable中,使可以序列化输出
            result.set(sum);
            //将计算结果逐条输出
            context.write(key, result);
        }
    }

    //启动mr的driver方法
    public static void main(String[] args) throws Exception {
        //得到集群配置参数
        Configuration conf = new Configuration();
        String[] otherArgs = (new GenericOptionsParser(conf,args)).getRemainingArgs();
        if(otherArgs.length<2){
            System.out.println("缺少变量:wordcount<in>[<in>...]<out>");
            System.exit(2);
        }
        //设置到本次的job实例中
        Job job = Job.getInstance(conf, "张驰のWordCount");
        //指定本次执行的主类是WordCount
        job.setJarByClass(WordCount.class);
        //指定map类
        job.setMapperClass(TokenizerMapper.class);
        //指定combiner类,要么不指定,如果指定,一般与reducer类相同
        job.setCombinerClass(IntSumReducer.class);
        //指定reducer类
        job.setReducerClass(IntSumReducer.class);
        //指定job输出的key和value的类型,如果map和reduce输出类型不完全相同,需要重新设置map的output的key和value的class类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        //指定输入数据的路径
        for(int i=0;i<otherArgs.length-1;++i){
            FileInputFormat.addInputPath(job,new Path(otherArgs[i]));
        }
        //指定输出路径,并要求该输出路径一定是不存在的
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length-1]));
        //指定job执行模式,等待任务执行完成后,提交任务的客户端才会退出!
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

WordCount部署运行

整个流程
在这里插入图片描述

  1. 刚开始namenode不存在,参考博客格式化了一下然后重启:./sbin/start-all.sh,出现了datanode
  2. 新建并写入两个文件:
#新建一个文件a
touch a
#打开vim编辑器写入a
vim a
#保存并退出
:wq

在这里插入图片描述
3. 上传到hdfs

#上传
./bin/hdfs dfs -put b input
#检查是否上传成功
./bin/hdfs dfs -ls input
  1. 在IDEA中编写代码程序,编写完成后打包jar包
    参考博客
    在这里插入图片描述

p.s. 其中出现了一个错误:IDEA /META-INF/MANIFEST.MF’ already exists in VFS,这是因为之前已经IDEA打包过这个项目了,找到MF目录,把它删了重新打包即可。参考博客解决

  1. 打包完成之后把jar包放在/usr/local/hadoop中,然后启动Hadoop运行jar包
./bin/hadoop jar WordCount.jar input output
  1. 最后,我们可以运行下面的命令查看结果:
./bin/hadoop fs -cat output/*

在这里插入图片描述

最后记录几个坑

  1. IDEA创建jar包的时候会把jar包放在一个同名的文件夹中,所以运行的时候需要把里面的jar包拿出来放到/usr/local/hadoop中,然后运行,否则的话就只是在运行一个文件夹
  2. 不需要创建output文件夹,否则在第5步的时候会报已经存在output的错误,删除output即可
/usr/loca/hadoop/bin/hadoop fs -rm -r output

参考

  1. 博客:Hadoop数据类型
  2. 博客:MapReduce实现WordCount
  3. 一起学Hadoop——使用IDEA编写第一个MapReduce程序(Java和Python)
  4. 深入理解java的static关键字
  5. Hadoop的启动与停止
  6. 林子雨《大数据原理与应用 第二版》p150
  7. 厦大林子雨 HSDF的文件操作
  8. 无法访问 org.apache.commons.cli.Options怎么解决?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值