Hadoop的搭建和第一個Hadoop小項目:單詞計數

Hadoop的搭建

我本身是在windows10上搭建的hadoop。java

參考資料以下:git

1.hadoop詳細安裝及配置github

2.winutils下載apache

3.hadoop3.0.3下載windows

4hadoop啓動報錯java.lang.NoClassDefFoundError:/org/apache/hadoop/yarn/server/timelineCollectorManager設計模式

第一個Hadoop小項目:單詞計數

單詞計數應該是不少人入門Hadoop的第一個小項目。我本身看的參考資料是《MapReduce設計模式》。運做這個小例子是不須要啓動Hadoop的。app

採坑總結:
(1)Caused by: java.io.FileNotFoundException: HADOOP_HOME and hadoop.home.dir aroop

我本身的解決方案是在系統變量添加HADOOP_HOME,在系統變量的PATH裏添加bin,重啓IDEA。以前在用戶變量裏添加過不知道爲何沒生效,因此在系統變量里加。用如下代碼驗證:學習

System.out.println(System.getenv("HADOOP_HOME"));
System.out.println(System.getenv("PATH"));

若是有些人報錯說找不到winutils.exe,須要去下載winutils的包,把對應版本的bin文件夾替換hadoop的bin。我在【hadoop的搭建】部分的參考資料有給下載的github地址。spa

(2)Maven的依賴問題。

Exception in thread "main" java.lang.VerifyError: Bad return type
'org/apache/hadoop/mapred/JobStatus' (current frame, stack[0]) is not assign 'org/apache/hadoop/mapreduce/JobStatus'

這個我在網上沒有找到解決方法,可是個人程序是參照《MapReduce設計模式》來的,肯定應該不是程序的問題以後,應該只能是Maven依賴的問題。修改後,個人項目的依賴包括:hadoop-common、hadoop-hdfs、hadoop-mapreduce-client-core、hadoop-mapreduce-client-jobclient、hadoop-mapreduce-client-common。版本都是3.0.3,由於我搭建的Hadoop版本是3.0.3。

(3)也是Maven依賴問題。

java.io.IOException: Cannot initialize Cluster. Please check your configuration for mapreduce.framework.name and the correspond server addresses.

添加hadoop-mapreduce-client-jobclient、hadoop-mapreduce-client-common這兩個依賴就好。
參考資料:https://blog.csdn.net/qq_2012...

完整的代碼
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.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;

import org.apache.hadoop.fs.Path;

import java.io.IOException;
import java.util.StringTokenizer;

/**
 * @Author liuffei
 * @Date 2019/7/13 9:41
 * @Description
 */
public class CommentWordCount {

    //Mapper<Object, Text,Text, IntWritable>表示輸入鍵,輸入值,輸出鍵,輸出值
    //mapper輸入的鍵值是在做業配置的FileInputFormat中定義的。
    public static class WordCountMapper extends Mapper<Object, Text,Text, IntWritable> {
        //設置計數爲1
        IntWritable one = new IntWritable(1);
        Text word = new Text();

        //覆蓋了Mapper類的map方法
        public void map(Object key, Text value, Context context) throws IOException, InterruptedException{
            String txt = value.toString();
            //將輸入值中的非字母替換爲空字符串
            txt = txt.replaceAll("[^a-zA-Z]","");
            StringTokenizer stringTokenizer = new StringTokenizer(txt);
            while(stringTokenizer.hasMoreTokens()) {
                word.set(stringTokenizer.nextToken());
                //將每一個單詞計數爲1,並保存。
                context.write(word, one);
            }
        }
    }

    //Reducer<Text, IntWritable,Text, IntWritable>表示輸入鍵,輸入值,輸出鍵,輸出值
    //Reducer的輸入鍵輸入值應該和Mapper的輸出鍵輸出值的類型保持一致
    public static class IntSumReducer extends Reducer<Text, IntWritable,Text, IntWritable> {

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

    public static void main(String[] args){
        try {
            Configuration conf = new Configuration();
            String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
            if(otherArgs.length != 2) {
                System.err.println("need enter input and output directory path");
                System.exit(2);
            }
            Job job = Job.getInstance(conf, "Word Count");
            //與本身定義的類名保持一致
            job.setJarByClass(CommentWordCount.class);
            //與本身定義的Mapper類和Reducer類保持一致
            job.setMapperClass(WordCountMapper.class);
            job.setCombinerClass(IntSumReducer.class);
            job.setReducerClass(IntSumReducer.class);
            //設置的輸出鍵和輸出值和mapper定義的須要保持一致。
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(IntWritable.class);
            //輸入輸出路徑
            FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
            FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
            System.exit(job.waitForCompletion(true)?0:1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

運行main方法以前,我在本身的項目的src同級目錄創建了input文件夾,並創建了兩個txt文件(注意文件的讀取是按行的,因此每一個單詞單獨一行)。運行main方法時,添加輸入輸出路徑。文件夾的路徑你們能夠本身定義。output文件夾不須要本身創建,會自動創建,每次運行時須要把以前生成的output文件夾刪除,否則會報output文件夾已經存在的錯。

參數設置

文件夾的位置以及輸出

以上就是本身的一些總結,學習Hadoop道阻且長,但願本身能夠堅持下去。

相關文章
相關標籤/搜索