大数据Hadoop第七周——Eclipse环境下java语言mapreduce程序开发环境配置+WordCount.java详解...

大数据第七周

1 Eclipse环境下java语言mapreduce程序开发环境配置

1.1 拷贝eclipse软件

先拷贝到根目录下,然后解压

tar -zxvf eclipse-java-2020-03-R-linux-gtk-x86_64.tar.gz

打开eclipse:进入eclipse 文件夹,输入:./eclipse

1.2 下载hadoop-eclipse插件

下载hadoop-eclipse-plugin-2.6.0.jar本插件与我们使用的hadoop版本2.7.7不对应,使用过程中有可能出现警告提示。实际开发过程中应该使用对应版本的插件。当前之所以使用是因为时间问题。

 eclipse下hdfs配置

将hadoop-eclipse-plugin-2.6.0.jar拷贝到eclipse的路径下的dropins文件夹下(老版本放plugins,现在时dropins)。重启eclipse,点击windows,选择Preferences,出现下面界面。

点击左边的"Hadoop/Mapreduce",出现如下界面。

点击右边的"Browse",选择hadoop软件的安装目录(注意不是bin的),点击"Apply and Close"。

1.4 创建并配置Mapreduce Locations

如下图,从window菜单进入,选择"Other"。

选择Mapreduce Locations,点击"Open"。

出现如下界面:

点击下方的图标,打开如下界面:

在"Location name"栏中填入一个名字,任意字符串都行。

Map/Reduce(V2)Maseter标签页的Host,需要填入master节点的IP地址,填入其它内容(比如域名)会出现问题。

端口号,Map Reduce的Port填写yarn.site.xml里的yarn.resourcemanager.address。网上有多种说法,我们填8032。

DFS Master标签页中,端口号Port填写core-site.xml中的fs.defaultF5。

填好后结果如下:

点击"finish"。

2 新建Mapreduce项目

2.1 从主菜单file开始,如下图点击"Other"。

选择"Map/Reduce Project"。

点击next,输入名字,注意建立的位置。

填入名字后,点击"Finish",出现如下界面:

在左侧可以看到HDFS文件存储情况。

输入:hadoop fs -mkdir /aaa新建一个文件夹存放hadoop fs -put abc.txt/上传的文件。

接着新建一个Java Package,使用默认名字。

接着新建一个class,要把main加上。

从如下路径,将WordCount.java(官方demo)文件里的内容拷贝到新建的class文件里。

3 WordCount程序解释

WorldCount相当于MapReduce中的helloworld,它主要完成的任务是单词计数,即统计一系列文本文件中每个单词出现的次数。在Map端进行文章单词拆分,并且以k-v即 word-1这种形式发送出去,接着MapReduce在reduce端,相同的key即相同的word会把所有的1放在Iterable<Text> values中,只需要统计Iterable中Text有多少个1即可,最后输出。

从main开始。

3.1 main的参数

public static void main(String[] args) throws Exception {
    /*main函数有形参,所以运行时需要有一个参数传入,类型是String[],
    * 数组元素数量没有指定,即数组大小可以任意。
  * 数组:[5,6,7,8]索引是:0,1,2,3,4数组的长度length=5。
  * For(i=0;i<数组.length-1;i++)数组[i]数组最后一个元素没有使用。
     */
  Configuration conf = new Configuration();
  String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
  if (otherArgs.length < 2) {//输入的参数数量不小于2,否则会报错
  System.err.println("Usage: wordcount <in> [<in>...] <out>");
  System.exit(2);

  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]));
}

3.2 main的流程

Hadoop都是以作业(job)形式运行用户程序。首先要告诉框架调用哪个类,指定本业务job要用的是mapper/Reducer业务类。

//job是一个对象。类实例化以后才是一个对象。getInstance用反射的方式获得一个实例,传入两个参数。其中,conf是输入路径和输出路径,另一个参数是字串,即这个job任务的名称。
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);//job是用哪一个class进行操作的。
job.setMapperClass(TokenizerMapper.class);//用TokenizerMapper分解任务
job.setCombinerClass(IntSumReducer.class);//将任务复合
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);//设置输出键值对的键的数据类型是Text.class
job.setOutputValueClass(IntWritable.class); //设置输出键值对的值的数据类型是IntWritable.class,即int型

3.3 TokenizerMapper程序

map端主要任务是拆分单词。输入为一个split中的数据,对split中的数据进行拆分,并以 < key, value> 对的格式保存数据,其中 key 的值为一个单词,value的值固定为 1。如 < I , 1>、< wish, 1> …

输入的参数含义分别为:

Object:输入< key, value >对的 key 值,此处为文本数据的起始位置。

Text:输入< key, value >对的 value 值,此处为一段具体的文本数据。

Text:输出< key, value >对的 key 值,此处为一个单词。

IntWritable:输出< key, value >对的 value 值,此处固定为 1。

public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{
// 从hadoop程序包Mapper中继承过来并在这个类的继承类中至少自定义实现 Map() 方法,其中 org.apache.hadoop.mapreduce.Mapper 
//要求的参数有四个(keyIn、valueIn、keyOut、valueOut),即Map()任务的输入和输出都是< key,value >对的形式。
  private final static IntWritable one = new IntWritable(1);
  //私有静态常量Int数据类型,对象的值是1,即one始终是1
  private Text word = new Text();//word是text数据类型,即string类型。
  // map通过参数指定重写了Mapper里的方法,Object是最原始的数据类型,说明key可以是任意的数据类型。Value是一个string。
  public void map(Object key, Text value, Context context)
  throws IOException, InterruptedException {
    // itr是个分词器。先将传进来的文件内容value转为string类型,然后对它进行分词,结果保存在itr。
    StringTokenizer itr = new StringTokenizer(value.toString());
    //把词变成一个个,每个词作为一个键值对输出一次,写入到context上下文里。
    //键是词,值一直是1
    while (itr.hasMoreTokens()) {//判断是否还有词
      word.set(itr.nextToken());//如果有就送给word将其写入word
      context.write(word, one);
    }
  }
}

把输入数据分成一个一个的词,然后输出一个一个的键值对。每个键值对的值都是1。有多少个词就有多少个键值对,键是一个词,值是1。

3.4 IntSumReducer程序

统计单词个数。在map到reduce 的过程中,系统会自动进行combine、shuffle、sort等过程对map task的输出进行处理,因此reduce端的输入数据已经不仅仅是简单的< key, value >对的形式,而是一个一系列key值相同的序列化结构,如:< hello,1,1,2,2,3…>。因此,代码中value的值就是单词后面出现的序列化的结构:(1,1,1,2,2,3…….)

输入的四个参数含义分别为:

Text:输入< key, value >对的key值,此处为一个单词

IntWritable:输入< key, value >对的value值。

Text:输出< key, value >对的key值,此处为一个单词

IntWritable:输出< key, value >对,此处为相同单词词频累加之后的值。

public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
//IntSumReducer继承Reducer,重写这些对象与方法,Reducer 类的参数也是四个(keyIn、valueIn、keyOut、valueOut),即Reduce()任务的输入和输出都是< key,value >对的形式。
  private IntWritable result = new IntWritable();
  public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
  int sum = 0;
  //检测val的个数
  for (IntWritable val : values) {// val是从values里一个个遍历得到
    sum += val.get();//sum把val里面的值取出来加起来
  }
  result.set(sum);//把result的值赋成sum
  context.write(key, result);
  }
}

 所有代码:

package testHadoop1;

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;

public class WordCount {

  public static class TokenizerMapper 
       extends Mapper<Object, Text, Text, IntWritable>{
    
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
      
    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
      StringTokenizer itr = new StringTokenizer(value.toString());
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        context.write(word, one);
      }
    }
  }
  
  public static class IntSumReducer 
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();

    public void reduce(Text key, Iterable<IntWritable> values, 
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
      }
      result.set(sum);
      context.write(key, result);
    }
  }

  public static void main(String[] args) throws Exception {
    /*main函数有形参,所以运行时需要有一个参数传入,类型是String[],
     * 数组元素数量没有指定,即数组大小可以任意。
     */
    Configuration conf = new Configuration();
    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
    
    
    if (otherArgs.length < 2) {//输入的参数数量不小于2,否则会报错
      System.err.println("Usage: wordcount <in> [<in>...] <out>");
      System.exit(2);
    }
    Job job = Job.getInstance(conf, "word count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.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]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔡军帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值