最近在學習 hadoop , 這是一個非常優秀的分布式架構 , 在學習的過程中也遇到了很多的問題 , 幾度讓人崩潰 , 我現在說說我遇到的問題 , 現在記錄下來和以後友善翻閱 , 同時也希望給在剛剛學習hadoop的朋友們一點小小的幫助。
我在看了hadoop自己的WordCount Demo後,自己也寫了一個小Demo,但是遇到了問題 ,下面我先說一下問題所在:
我在本地建立 了一個檔案夾(in)作為輸入檔案夾,檔案夾内建立了兩個文本檔案 (1.txt 2.txt)
我的輸入檔案内容如下:
1.txt
hello hadoop
hello java
hello C++
2.txt
對于這兩個檔案我們期望得到的答案應該是:
hello 5
hadoop 2
java 2
C++ 1
但是我得到的結果卻是這樣的:
C++ 2
hadoop 3
hello 8
java 3
這對于一個初學者來說不是很讓人崩潰嗎,一開始我以為我程式寫錯了,但是我檢查了很多遍,還和hadoop自帶的程式對比了,保證沒有出現錯誤,但是是什麼地方出錯了呢,我試過很多方法,不知道是什麼地方的問題。困擾了很久,在我使用 linux指令 ls 的時候想起來了,可能是這樣的問題。下面看一張圖檔:

從上面的圖檔中,我們看一看到我的輸入檔案夾 in内不隻有我們認為隻有的1.txt 和2.txt 檔案,還多了 1.txt `和2.txt` ,這樣結果肯定就不正确了。
錯誤原因:
因為我是手動的在in檔案夾内建立了這兩個文本檔案, 原來在我建立檔案的同時生成了兩個該檔案的副本,這樣就出現了我一開始出現的問題,由于是剛開始使用 ubuntu系統 ,不熟悉裡面的機制,相信可能會有很多初學hadoop的朋友會遇到這樣的問題,希望會給大家一些幫助。
package cn.edu.ytu.botao.wordcount;
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
/**
* 單詞計數
* @author botao
*
*/
public class WordCount {
/**
* map 過程
* 繼承Mapper接口 設定map的輸入類型為 <Object,Text>
* 輸出類型為<Text. IntWritable>
*/
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{
//one 表示單詞出現一次
private final static IntWritable one=new IntWritable(1);
//word 用于存儲切下的單詞
private Text word=new Text();
/**
* 重寫map()方法
*/
@Override
protected void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
// TODO Auto-generated method stub
//super.map(key, value, context);
//對value(要計數的檔案進行單詞切割) 進行切分
StringTokenizer tokenizer=new StringTokenizer(value.toString());
//将切割後的單詞取出 輸出
while (tokenizer.hasMoreTokens()) {
word.set(tokenizer.nextToken());
//map 輸出格式 <Text,IntWritable>
context.write(word, one);
}
}
/**
* reduce 過程
* 繼承Reducer接口 設定輸入類型為 <Text,IntWritable> (該輸入類型正為 mapper 的輸出類型)
* 輸出類型為: <Text,IntWritable>
*/
public static class SumReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
//numResult 記錄單詞的頻數
private IntWritable numResult=new IntWritable();
/**
* 重寫reduce()方法
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values,
Context context)
throws IOException, InterruptedException {
// TODO Auto-generated method stub
int sum=0;
//對擷取的<key,value-list> 計算value的和
for (IntWritable val : values) {
sum+=val.get();
}
//将頻數存放到numResult 中
numResult.set(sum);
//收集結果
context.write(key, numResult);
}
}
}
}