手作業で作成された最初のMapReduceプログラム--wordcount

見積もり:

    以前、hadoopに付属する最初のサンプルwordcountを実行しました。今回は、自分で手書きしました。これは、プログラミング言語のhelloworldに相当します。
まず、MapReduceのどの部分を記述したいかを理解しましょう。hadoopファイルを処理するために、処理されるファイルは最初に多くの部分に分割され、別々に処理され、最後に結果が集約され
て最終的な処理結果が形成されます(つまり、分割統治の考え方)次に単語統計を見てみましょうたとえば、MapReduceプロセス全体のどの部分が、私たちが記述したコードであるかを確認します。

特定のMapReduceプロセスの例

まず、そのようなファイルがあり、ファイルの内容は次のとおりです:
hello world hello java
hello hadoop
は非常にシンプルで、ファイルは2行です。それで、hadoopはどのように単語統計を実行しますか?
ステップでそれを説明しましょう:ステップ1:これを読むファイルを作成し、このファイルの各行の単語を行ごとに分割して、多数のキー/値の結果を形成します。処理後、次のようになります
<hello、1>
<world、1>
<hello、1>
<java、1>
<hello、1>
<hadoop、1>
ステップ2:ソートソート後
、結果は次のようになります
<hadoop、1>
<hello、1>
<hello、1>
<hello、1>
<java、1>
<world 、1>
ステップ3:マージマージ
の結果は次のとおりです。
<hadoop、1>
<hello、1,1,1>
<java、1>
<world、1>
ステップ4:結果を収束します
<hadoop、1>
<hello 、3>
<java、1>
<世界、1>

4番目のステップが完了すると、統計という単語が実際に完了します。この特定の例を読んだ後、mapreduce処理プロセスをより明確に理解
する必要があります。次に、2番目と3番目のステップがhadoopフレームワークであることを知る必要があります完成させるために、実際にコードを記述する必要があるのは、最初と4番目のステップです。
最初のステップはMapプロセスに対応し、4番目のステップはReduceプロセスに対応します。

mapreduceコードを書く

次に、コードの最初と4番目のステップを完了する必要があります
。1.プロジェクトを


作成する通常のJavaプロジェクトを作成し、[次へ]をクリックして、自分でプロジェクト名を選択します
。2 . 当時使用されていたhadoopをインポートします。パッケージ、ここではhadoop-3.2.0バージョンを使用していますが、どのパッケージをインポートする必要がありますか?インポートするパッケージ

(1)hadoopディレクトリのshare / hadoop / commonにあるパッケージ(テストパッケージを除き、公式(テスト例、導入する必要はありません)
(2)。前のものと同じlibの下で共通のパッケージ
(3)。hadoopディレクトリの下のshare / hadoop / mapreduceの下のパッケージ
(4)前のものと同じmapreduceの下のライブラリ
次に、パッケージがアイデアでこれらのパッケージに導入されます。[ファイル]-> [プロジェクト構造
]- > [モジュール]をクリックし、導入された右側の小さなプラス記号をクリックします。

3.パッケージの導入が完了したら、WordCountというJavaファイルを作成し、コードの入力を開始します。
ここでコードを直接貼り付けます。__ インポート部分に注意してください。これは私と同じですか?__同じ名前のクラスが多数あるため、さまざまな瓶から来て、間違いを犯しやすいです。

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 java.io.IOException;
import java.util.StringTokenizer;

/**
 * @author wxwwt
 * @since 2019-09-15
 */
public class WordCount {

    /**
     * Object      : 输入文件的内容
     * Text        : 输入的每一行的数据
     * Text        : 输出的key的类型
     * IntWritable : 输出value的类型
     */
    private static class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {
        @Override
        protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            StringTokenizer itr = new StringTokenizer(value.toString());
            while (itr.hasMoreTokens()) {
                context.write(new Text(itr.nextToken()), new IntWritable(1));
            }
        }
    }

    /**
     * Text         :  Mapper输入的key
     * IntWritable  :  Mapper输入的value
     * Text         :  Reducer输出的key
     * IntWritable  :  Reducer输出的value
     */
    private static 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 item : values) {
                count += item.get();
            }
            context.write(key, new IntWritable(count));
        }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        // 创建配置
        Configuration configuration = new Configuration();
        // 设置hadoop的作业  jobName是WordCount
        Job job = Job.getInstance(configuration, "WordCount");
        // 设置jar
        job.setJarByClass(WordCount.class);
        // 设置Mapper的class
        job.setMapperClass(WordCountMapper.class);
        // 设置Reducer的class
        job.setReducerClass(WordCountReducer.class);
        // 设置输出的key和value类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        // 设置输入输出路径
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));
        // 待job执行完  程序退出
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }

}

マッパープログラム:

/**
 * Object      : 输入文件的内容
 * Text        : 输入的每一行的数据
 * Text        : 输出的key的类型
 * IntWritable : 输出value的类型
 */
private static class WordCountMapper extends Mapper<Object, Text, Text, IntWritable> {
    @Override
    protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
        StringTokenizer itr = new StringTokenizer(value.toString());
        while (itr.hasMoreTokens()) {
            context.write(new Text(itr.nextToken()), new IntWritable(1));
        }
    }
}

context是全局的上下文,先使用了StringTokenizer将value(也就是每行的数据)按照空格分成了很多份,StringTokenizer如果没有传入指定的分割符的话,默认会将
" \t\n\r\f" 空格制表符换行符等符号作为分隔符,然后使用nextToken()来遍历这个按照空格分割的字符串.context.write(new Text(itr.nextToken()), new IntWritable(1));
的意思就是将key/value写入到上下文中.
注:在hadoop编程中String是Text,Integer是IntWritable.这是hadoop自己封装的类.记住就好了,使用起来和原来的类差不多
这里就是写入了key为Text的单词,和value为Writable的1(统计数量).

Reduce程序:

/**
 * Text         :  Mapper输入的key
 * IntWritable  :  Mapper输入的value
 * Text         :  Reducer输出的key
 * IntWritable  :  Reducer输出的value
 */
private static 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 item : values) {
            count += item.get();
        }
        context.write(key, new IntWritable(count));
    }
}

reduce完成的是第四步的内容,我们看看上面的实例过程就回知道此时的输入参数大概是这样
<hello,1,1,1>
所以这里会有一个遍历values的过程,就是将这三个1给累加起来了.

程序入口:

public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
    // 创建配置
    Configuration configuration = new Configuration();
    // 设置hadoop的作业  jobName是WordCount
    Job job = Job.getInstance(configuration, "WordCount");
    // 设置jar
    job.setJarByClass(WordCount.class);
    // 设置Mapper的class
    job.setMapperClass(WordCountMapper.class);
    // 设置Reducer的class
    job.setReducerClass(WordCountReducer.class);
    // 设置输出的key和value类型
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);

    // 设置输入输出路径
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    // 待job执行完  程序退出
    System.exit(job.waitForCompletion(true) ? 0 : 1);
}

程序入口这里其实看注释就已经比较清楚了,都是设置一些mapreduce需要的参数和路径之类的,
照着写就行了.这里稍微要注意一点的就是

FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));

実行前にHadoopの最初のプログラムを確認する場合、コマンドはおそらく
hadoop jar WordCount.jar / input / wordcount / file1 / output / wcoutput
です。コードが変更されている場合、背後の2つのパラメーターはファイルの入力パスと出力パスです。パラメータの位置または他のパラメータを使用した操作の場合、
args添え字の位置に対応する必要あります。

4.実行するjarパッケージのエントリポイントを指定します。
コードが完成したら、パッケージ化できます。
まず、[ファイル]-> [プロジェクト構造]-> [成果物]-> +-> [JAR]-> [依存関係のあるモジュールから]を

選択し、WordCountのメインを選択して

、[ビルド]-> [ビルド]をクリックします。アーティファクト

は、ボックスをポップアップして[ビルド]を選択

し、プロジェクト内にoutディレクトリを生成し、その中に必要なWordCount.jarを見つけて、Hadoopが配置されているサーバーにアップロードします。
これで、以下の手順と前の記事と同じように、次を参照できます:hadoop run the first instance wordcount

予防:

直接実行できます

  hadoop jar WordCount.jar /input/wordcount/file1  /output/wcoutput

失敗して例外を報告します:

Exception in thread "main" java.io.IOException: Mkdirs failed to create /XXX/XXX
  at org.apache.hadoop.util.RunJar.ensureDirectory(RunJar.java:106)
  at org.apache.hadoop.util.RunJar.main(RunJar.java:150)

上記と同様。

この時点で、Licenseフォルダーとjarパッケージの内容を削除する必要があります。このリンクを参照できます:stackoverflow jar jar
内のライセンスのファイルとフォルダーを表示
jar tvf XXX.jar | grep -i license
and delete META-INF / LICENSE
zip -d XXX.jar META-INF / LICENSEの内容

総括する:

1. mapReduceの操作手順を理解します。これにより、mapとreduceのプロセスを記述するだけでよいことがわかります。中間手順は、hadoopフレームワークによって処理されています。将来、他のプログラムもこの手順を参照して書き込むことができます
。2. hadoopの文字列はテキストです。 IntegerはIntWritableです。間違って使用すると、例外が報告さ
れます。3。Mkdirsが/ XXX / XXXの作成に失敗したことを報告した場合、パスに問題がないかどうかを確認してください。問題がない場合は、jarパッケージのMETA-INF /を削除してください。ライセンス

参考資料:

1.https://hadoop.apache.org/docs/stable/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html
2.https://stackoverflow.com/questions/10522835/hadoop-java -io-ioexception-mkdirs-failed-to-create-some-path

おすすめ

転載: blog.csdn.net/sc9018181134/article/details/100865699