2017-01-18 5 views
1

Я получаю ArrayIndexOutofBoundsException рядом с String temp = word[5]; в моем картографе.ArrayIndexOutofBoundsException с Hadoop MapReduce

Я исследовал это, и я знаю, что ошибка происходит из (когда входные данные пуст или длина меньше или больше показателя, указанного в коде. Мои данные имеет несколько пустых значений ячеек)

Я попытался поймать ошибку индекса массива, используя следующий код, но он все еще дает мне ошибку.

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

Отбрасывая исключение в сигнатуре метода, вы в основном заставляете весь экранный блок останавливаться всякий раз, когда он сталкивается с одной «плохой» строкой данных. То, что вы на самом деле хотите сделать, - это заставить mapper игнорировать эту строку данных, но продолжать обрабатывать другие строки.

Вы должны проверить длину 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), которые будут обметать до выше.

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 '}' 
    } 
    } 

}