Hadoop中的Reducer任务表现不尽如人意

时间:2016-04-16 20:08:24

标签: hadoop mapreduce

我有2个输入文件用于Hadoop MapRed任务。

该计划的输入为input.txt,其中包含每行PaperID keyword1 keyword2 FieldID

p20 k j f3
p21 k j f11
p22 k j f3
p23 k j f2
p23 k j f1

Reducer类中使用的文件sammap.txt包含在每行FieldID FieldName

f1 AI
f2 DB
f3 DB
f4 AI

代码如下:     包多拉多;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
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 Dorado {

  public static class TokenizerMapper
       extends Mapper<Object, Text, Text, Text>{

    private Text word = new Text();
    public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
        String str = value.toString().replaceAll(" +", " ").trim(), fir="", lst="";
        if (!str.equals("")) {
            fir = str.substring(0, str.indexOf(" "));
            lst = str.substring(str.lastIndexOf(" ")+1);

            context.write(new Text(fir), new Text(lst));
        }


    }
  }

  public static class IntSumReducer
       extends Reducer<Text,Text,Text,Text> {
  //  private IntWritable result = new IntWritable();
    private HashMap<Text, Text> fieldToClass = new HashMap<>();
    public void reduce(Text key, Iterable <Text> value,Context context) throws IOException, InterruptedException {
        FileReader fr = new FileReader("sammap.txt");
        BufferedReader br = new BufferedReader(fr);
        String str=null;
        while ((str = br.readLine()) != null) {
            String st[] = str.split(" +");
            fieldToClass.put(new Text(st[0].trim()), new Text(st[1].trim()));

            //System.out.println("--"+st[0].trim()+"--"+ st[1].trim()+"--");
        }
        fr.close();

        for (Text field : value) {
            System.out.println(key + "-->" + field);

            if (fieldToClass.containsKey(field))
                context.write(key, fieldToClass.get(field));
        }

    }
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    Job job = Job.getInstance(conf, "dorado");
    job.setJarByClass(Dorado.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(Text.class);
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

Hashmap fieldToClass的关键字为FieldID,值为FieldName。

控制台上的输出,用于Reducer类中的以下代码段:

for (Text field : value) {
    System.out.println(key + "-->" + field);
    if (fieldToClass.containsKey(field))
        context.write(key, fieldToClass.get(field));
}

就是这样:

p20-->DB
p22-->DB
p23-->AI
p23-->DB

但是我们希望输出格式为:

p20-->f3
p22-->f3
p23-->f1
p23-->f2

此程序的最终输出文件中也没有输出。该文件为空。

我们在文件中期望的正确输出是:

p20 DB
p22 DB
p23 DB
p23 AI

为什么程序行为错误?有哪些可能的解决方案?

1 个答案:

答案 0 :(得分:1)

您的整个过程可以在映射器内部完成。使用mapper的setup函数初始化HashMap。直接在HashMap中搜索fieldId并获取它的值并将其写入上下文。在可迭代值的for循环内的reducer中输出相同的东西。