使用Java编写第一个MapReduce程序

演示目标

编写一个MapReduce,用于计算文章中所有词语的出现次数(WordCount)。

演示环境

搭建MR工程

使用 IDEA新建一个Maven工程

配置pom.xml

<properties>
    <hadoop.version>2.6.5</hadoop.version>
</properties>

<dependencies>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-hdfs</artifactId>
      <version>${hadoop.version}</version>
      <exclusions>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <version>${hadoop.version}</version>
      <exclusions>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>${hadoop.version}</version>
      <exclusions>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
        <exclusion>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>

编写WordCountMapper.java

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

import java.io.IOException;

/**
 * Description ...
 *
 * @author NickZxing
 * @date 2019/7/29 17:36
 */
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String[] strArray = StringUtils.split(value.toString(), ' ');

        for (String str : strArray) {
            context.write(new Text(str), new IntWritable(1));
        }
    }
}

编写WordCountReducer.java

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

import java.io.IOException;

/**
 * Description ...
 *
 * @author NickZxing
 * @date 2019/7/29 17:56
 */
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int count = 0;
        for (IntWritable i : values) {
            count += i.get();
        }
        context.write(key, new IntWritable(count));
    }
}

编写启动类Startup.java

import nick.hadoop.mapper.WordCountMapper;
import nick.hadoop.reducer.WordCountReducer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * Description ...
 *
 * @author NickZxing
 * @date 2019/7/30 9:22
 */
public class Startup {

    public static void main(String[] args) {
        Configuration configuration = new Configuration();
        try {
            FileSystem fileSystem = FileSystem.get(configuration);

            Job job = Job.getInstance(configuration);
            job.setJarByClass(Startup.class);
            job.setJobName("WordCount");
            job.setMapperClass(WordCountMapper.class);
            job.setReducerClass(WordCountReducer.class);
            job.setMapOutputKeyClass(Text.class);
            job.setMapOutputValueClass(IntWritable.class);

            FileInputFormat.addInputPath(job, new Path("/input"));

            Path outputPath = new Path("/output");

            if (fileSystem.exists(outputPath))
                fileSystem.delete(outputPath, true);

            FileOutputFormat.setOutputPath(job, outputPath);

            if (job.waitForCompletion(true))
                System.out.printf("Job执行成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

打包工程

  • 在IDEA中打开Project Structure(快捷键:Ctrl+Shift+Alt+S);
  • 依次选择下图中红框部分:
    在这里插入图片描述
  • 选择入口类(Startup.java),并将META-INF的目录修改为src目录;
    在这里插入图片描述
  • 依次选择下图中红框部分,选择完毕后,IDEA便开始打包工程:
    在这里插入图片描述
    在这里插入图片描述
  • 打包完毕后,可以看到打包好的jar包:
    在这里插入图片描述

部署MR工程

使用编写好的MR工程jar包完成WordCount任务

上传jar包到服务器

将MR工程上传到Hadoop集群中的服务器:
在这里插入图片描述

运行jar包

使用hadoop jar xxxx.jar运行:
在这里插入图片描述

好的,以下是用Java编写MapReduce程序的基本步骤: 1. 编写Mapper类: Mapper类是MapReduce的第一步,负责将输入数据转换为键值对。通常情况下,Mapper类需要继承自org.apache.hadoop.mapreduce.Mapper类,并重写map方法。map方法的输入为键值对,输出为键值对,可以使用context.write方法将结果写入到输出中。 例如,假设我们有一些文本文件,需要计算每个单词出现的次数,我们可以编写如下的Mapper类: ``` public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> { private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); StringTokenizer tokenizer = new StringTokenizer(line); while (tokenizer.hasMoreTokens()) { word.set(tokenizer.nextToken()); context.write(word, one); } } } ``` 2. 编写Reducer类: Reducer类是MapReduce的第二步,负责将Mapper的输出进行聚合,生成最终的输出。通常情况下,Reducer类需要继承自org.apache.hadoop.mapreduce.Reducer类,并重写reduce方法。reduce方法的输入为键值对的迭代器,输出为键值对,可以使用context.write方法将结果写入到输出中。 例如,我们可以编写如下的Reducer类: ``` public class WordCountReducer 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); } } ``` 3. 配置Job: 在编写MapReduce程序之前,需要进行一些配置,以便Hadoop可以正确地运行MapReduce作业。通常情况下,需要创建一个org.apache.hadoop.mapreduce.Job对象,并设置输入和输出路径,MapperReducer类,以及一些其他的配置。 例如,我们可以编写如下的Job配置: ``` Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(WordCountMapper.class); job.setCombinerClass(WordCountReducer.class); job.setReducerClass(WordCountReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); ``` 4. 运行Job: 最后一步是运行Job。通常情况下,可以使用job.waitForCompletion方法提交Job,并等待作业完成。 例如,我们可以编写如下的Main方法: ``` public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(WordCountMapper.class); job.setCombinerClass(WordCountReducer.class); job.setReducerClass好的,下面是一个使用Java编写MapReduce程序的示例: 首先,我们需要定义MapperReducer类。Mapper类负责将输入数据分解成一个个key-value对,而Reducer类则负责将Mapper输出的key-value对合并成最终的结果。 下面是一个简单的Mapper类的示例代码: ```java 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 WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> { private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); String[] words = line.split(" "); for (String word : words) { this.word.set(word); context.write(this.word, one); } } } ``` 这个Mapper类用于对输入的文本数据进行单词计数。它将每一行文本数据拆分成多个单词,并输出一个key-value对,其中key为单词,value为1。 下面是一个简单的Reducer类的示例代码: ```java import java.io.IOException; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> { public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable value : values) { sum += value.get(); } context.write(key, new IntWritable(sum)); } } ``` 这个Reducer类用于将Mapper输出的key-value对进行合并。它将相同key的value值累加起来,最终输出一个key-value对,其中key为单词,value为该单词在输入文本中出现的次数。 接下来,我们需要编写一个Main函数,用于启动MapReduce任务。下面是一个简单的Main函数的示例代码: ```java import org.apache.hadoop.fs.Path; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class WordCount { public static void main(String[] args) throws Exception { if (args.length != 2) { System.err.println("Usage: WordCount <input path> <output path>"); System.exit(-1); } Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(WordCountMapper.class); job.setReducerClass(WordCountReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } } ``` 这个Main函数用于设置MapReduce任务的各项 我可以为您提供一些有关如何使用Java编写MapReduce程序的指导。好的,以下是使用Java编写MapReduce程序的基本步骤: 1. 实现MapperMapper类负责将输入数据分成一系列的键值对(key-value pair),其中key表示数据的某个属性,value则表示该属性对应的值。 例如,假设我们的输入是一些单词组成的文本文件,那么Mapper类的主要工作就是将每个单词作为key,将其出现的次数作为value。Mapper类通常需要继承自org.apache.hadoop.mapreduce.Mapper类,并实现其map()方法。 以下是一个示例Mapper类的代码: ``` 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 WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> { private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); String[] words = line.split("\\s+"); for (String word : words) { this.word.set(word); context.write(this.word, one); } } } ``` 在这个例子中,我们将输入数据中的每个单词作为key,并将其出现的次数作为value,其中key和value的类型分别为Text和IntWritable。我们使用split()方法将每行文本按照空格分割成单词,并将每个单词和一个常量值1作为一组键值对输出。 2. 实现Reducer类 Reducer类负责将Mapper输出的一组键值对进行聚合,以得到最终的输出结果。 例如,如果我们要统计单词出现的总次数,那么Reducer类的主要工作就是将输入的一系列键值对中,具有相同key的所有value相加,并将其作为输出。 Reducer类通常需要继承自org.apache.hadoop.mapreduce.Reducer类,并实现其reduce()方法。 以下是一个示例Reducer类的代码: ``` import java.io.IOException; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> { public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable value : values) { sum += value.get(); } context.write(key, new IntWritable(sum)); } } ``` 在这个例子中,我们将Mapper输出的每个单词作为key,将其出现的次数作为value,并使用reduce()方法将具有相同key的value进行求和。输出的key和value的类型仍然为Text和IntWritable。 3. 配置Job对象 Job对象负责将MapperReducer类组合在一起,并指定输入和输出路径等相关参数。Job对象通常需要通过Configuration对象进行配置。 以下是一个示例Job对象的代码: ``` import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path好的,以下是一个用Java编写MapReduce程序的示例: ``` 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; 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 { Configuration conf = new Configuration(); 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); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } } ``` 这个程序实现了一个简单的词频统计功能。主要包含三个部分: 1. Mapper:将输入文件中的每个单词转换成键值对,键为单词,值为1。 2. Reducer:将Mapper输出的键值对按照键进行分组,并将每组键值对的值相加得到该单词的出现次数。 3. Main函数:设置输入输出路径、指定MapperReducer类等。 请注意,在运行这个程序之前,需要先安装和配置Hadoop环境,并将程序打包成jar包,然后使用以下命令在Hadoop集群上运行: ``` hadoop jar wordcount.jar input_dir output_dir ``` 其中,`wordcount.jar`为打包好的程序jar包,`input_dir`为输入文件路径,`output_dir`为输出文件路径。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值