我的映射器中的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));
}
}
}
如果你能给我任何关于错误是否在这个代码中的提示或提示,或者我应该看看其他地方,这将节省很多压力!
答案 0 :(得分:0)
通过在方法签名中抛出异常,您基本上会导致整个映射器在遇到单个“坏”数据行时停止。您实际想要做的是让映射器忽略该行数据,但继续处理其他行。
您应该在word[]
之后立即检查split()
的长度。如果时间不够,请停止处理该行。您还需要检查month
和temp
在提取后是否有效。怎么样:
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 StringUtils
和ArrayUtils
类 - 它们提供了StringUtils.isEmpty(temp)
和ArrayUtils.isEmpty(word)
之类的方法,这些方法可以解决上述问题。
答案 1 :(得分:0)
我建议使用自定义计数器,每次找到空单元格时都会增加。这将为您提供数据中存在多少这样的行的图片。 除了一些其他效率修改,我的建议如下:
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 '}'
}
}
}