【问题标题】:ArrayIndexOutofBoundsException with Hadoop MapReduceArrayIndexOutofBoundsException 与 Hadoop MapReduce
【发布时间】:2017-01-18 08:26:48
【问题描述】:

在我的映射器中,ArrayIndexOutofBoundsException 旁边是 String temp = word[5];

我对此进行了研究,我知道错误来自什么(当输入数据为空或长度小于或大于代码中指定的索引时。我的数据有一些空单元格值)

我尝试使用以下代码捕获数组索引错误,但它仍然给我错误。

import java.io.IOException;
import java.util.*;

import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.*;

public class AvgMaxTempMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, DoubleWritable> {

  public void map(LongWritable key, Text value, OutputCollector<Text, DoubleWritable> output, Reporter reporter) throws IOException {


    String line = value.toString();

    if(line != null && !line.isEmpty() && str.matches(".*\\d+.*"));
        String [] word = line.split(",");
        String month = word[3];
        String temp = word[5];
        if (temp.length() > 1 && temp.length() < 5){
            Double avgtemp = Double.parseDouble(temp);


        output.collect(new Text(month),  new DoubleWritable(avgtemp));
    }
  }
}       

如果您可以给我任何提示或提示,说明错误是否在此代码中,或者我应该查看其他地方,这将节省很多压力!

【问题讨论】:

    标签: java hadoop mapreduce indexoutofboundsexception


    【解决方案1】:

    通过在方法签名中抛出异常,您基本上会导致整个映射器在遇到单个“坏”数据行时停止。您真正想要做的是让映射器忽略该行数据,但继续处理其他行。

    您应该在split() 之后立即检查word[] 的长度。如果不够长,请停止处理该行。您还需要检查 monthtemp 在提取它们后是否有效。怎么样:

    String [] word = line.split(",");
    if (word == null || word.length < 6) {
        break;
    }
    
    String month = word[3];
    if (month != null) {
        break;
    }
    
    String temp = word[5];
    
    if (temp != null && temp.length() > 1 && temp.length() < 5) {
        try {
            Double avgtemp = Double.parseDouble(temp);
        } catch (NumberFormatException ex) {
            //Log that you've seen a dodgy temperature
            break;
        }
        output.collect(new Text(month), new DoubleWritable(avgtemp));
    }
    

    验证 MapReduce 作业中的数据非常重要,因为您永远无法保证您将获得什么作为输入。

    您可能还想查看 ApacheCommons StringUtilsArrayUtils 类 - 它们提供了诸如 StringUtils.isEmpty(temp)ArrayUtils.isEmpty(word) 之类的方法,可以使上述内容更加整洁。

    【讨论】:

      【解决方案2】:

      我建议改用自定义计数器,每次找到一个空单元格时都会增加该计数器。这将使您了解数据中存在多少这样的行。 除了其他一些效率修改之外,我的建议如下:

      import java.io.IOException;  //do you still need this?
      import java.util.*;
      
      import org.apache.hadoop.io.*;
      import org.apache.hadoop.mapred.*;
      
      public class AvgMaxTempMapper extends MapReduceBase implements Mapper<LongWritable, Text, Text, DoubleWritable> {
      
        public static enum STATS {MISSING_VALUE};
        private Text outKey = new Text();
        private DoubleWritable outValue = new DoubleWritable();      
      
        public void map(LongWritable key, Text value, OutputCollector<Text, DoubleWritable> output, Reporter reporter) throws IOException {
      
      
          String line = value.toString();
      
          if(line.matches(".*\\d+.*"));
              String [] word = line.split(",");
              if (word.length < 6) { //or whatever else you consider expected
                  reporter.incrCounter(STATS.MISSING_VALUE,1); //you can also print/log an error message if you like                
                  return;
              }
              String month = word[3];
              String temp = word[5];
              if (temp.length() > 1 && temp.length() < 5){
                  Double avgtemp = Double.parseDouble(temp);                  
                  outKey.set(month);
                  outValue.set(avgtemp);
                  output.collect(outKey, outValue);
              } //you were missing this '}'
          }
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-11
        • 1970-01-01
        • 1970-01-01
        • 2015-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多