在MapReduce中使用自定义分区程序时清空输出

时间:2017-07-04 16:15:37

标签: java hadoop mapreduce

问题陈述:

输入

  

Monami 45000 A
      Tarun 34000 B
      Riju 25000 C
      丽塔42000 A
      Mithun 40000 A
      Archana 21000 C
      Shovik 32000 B

我想在Mapreduce中使用自定义分区程序将员工记录与三个不同输出文件中的A,B和C级分开。

输出1

  

Monami 45000 A
      丽塔42000 A
      Mithun 40000 A

输出2

  

Tarun 34000 B
      Shovik 32000 B

输出3

  

Riju 25000 C
      Archana 21000 C

地图代码:

import java.io.IOException;

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

public class Map 
            extends Mapper<LongWritable,Text,Text,Text>
{

//private Text key1 = new Text();
//private Text value1 = new Text();

@Override
protected void map(LongWritable key,Text value,Context context) 
                        throws IOException,InterruptedException
{   
    String line = value.toString();
    String[] part = line.split("\t");
    int len = part.length;

    //System.out.println(len);
    if (len == 3)
    {
        context.write(new Text(part[2]), new Text(part[0]+"\t"+part[1]));
        //System.out.println(part[0]+part[1]+part[2]);
    }

}

分区代码

 import org.apache.hadoop.io.Text;
 import org.apache.hadoop.mapreduce.Partitioner;

 public class CustomPartitioner
            extends Partitioner<Text,Text>
{
@Override
public int getPartition(Text key, Text value, int numReduceTasks)
    {
    if(numReduceTasks==0)
        return 0;
    if(key.equals(new Text("A")))
        return 0;
    if(key.equals(new Text("B")))
        return 1;
    else 
        return 2;
    }
    }

减少代码

 import java.io.IOException;
 import java.util.Iterator;

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

 public class Reduce 
                extends Reducer<Text,Text,Text,Text>
 {

@Override
protected void reduce(Text key,Iterable<Text> values,Context context)
                                        throws IOException,InterruptedException
    {
        Iterator<Text> itr = values.iterator();

        while(itr.hasNext())
        {
            context.write(new Text(itr.next().getBytes()),new Text(key));
        }


    }
   }

驱动程序类

 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;


public class MapReduceDriver
{
public static void main(String[] args) throws Exception
{
    Job job = new Job();

    job.setJarByClass(MapReduceDriver.class);
    job.setJobName("Custom Partitioner");

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

    job.setMapperClass(Map.class);
    job.setPartitionerClass(CustomPartitioner.class);
    job.setReducerClass(Reduce.class);
    job.setNumReduceTasks(3);

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(Text.class);

    System.exit(job.waitForCompletion(true)?0:1);

}

}

代码运行时没有任何错误,但三个reduce输出文件为空。此外,当作业运行时,它将地图输出字节显示为零。因此,我认为地图不会生成任何键值对。但我无法找出原因。你能帮我找到错误吗?

另外我还有一个困惑:在Map类中,当检查变量len时&gt; 0,然后我得到ArrayIndexOutOfBoundsException但它运行良好,没有任何异常如果检查与== 3.为什么它抛出一个异常&gt; 0?

1 个答案:

答案 0 :(得分:1)

问题是您的输入数据(如此处粘贴)不是以制表符分隔,而是以逗号分隔。它应该可以正常工作,如果你替换这一行:

 String[] part = line.split("\t");

这一行:

String[] part = line.split(" ");

检查len > 0时遇到异常的原因是你的字符串没有被分成任何子部分,所以len是1.然后它满足if条件并尝试执行部分位置2的东西,不存在。

在现有代码中,len不是3,因此代码永远不会进入if块,因此不会抛出任何异常。