#hadoop #mapreduce #hadoop2
#hadoop #mapreduce #hadoop2
Вопрос:
У меня есть сценарий для вычисления среднего значения двух столбцов в map reduce. Итак, что я сделал, я получил значения из файла с помощью mapper и объединил их в текст, а затем попытался записать их в контекст, как показано ниже.
class TestMapper extends Mapper<LongWritable, Text, Text, Text> {
private Text outputKey;
private Text outputVal;
@Override
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//more code here
context.write(outputkey,OutputVal);
}
}
Комментарии:
1. Да, вы можете использовать текст в качестве значения, фактически вы можете использовать любой другой тип данных, поддерживаемый платформой Hadoop. У вас есть какие-либо проблемы? если да, поделитесь своим кодом и трассировкой стека исключения.
2. Спасибо за беспокойство, Азим. Я добился этого, изменив типы данных в объекте задания.
3. Было бы лучше, если бы вы могли прочитать Hadoop от Oreilly’s: The Definitive Guide book. Это потрясающе. Отлично, ваша проблема решена 🙂
Ответ №1:
Здесь вы должны использовать пользовательский тип данных, например, класс TextPair, который имеет два текстовых элемента для хранения необходимых вам данных. Ниже приведен пример кода, который используется для вывода пары строк в значении контекста mapper.
// Mapper's map code
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, TextPair>.Context context)
throws IOException, InterruptedException {
String line = value.toString();
String year = line.substring(15, 19);
int airTemperature;
if (line.charAt(87) == ' ') { // parseInt doesn't like leading plus signs
airTemperature = Integer.parseInt(line.substring(88, 92));
} else {
airTemperature = Integer.parseInt(line.substring(87, 92));
}
String quality = line.substring(92, 93);
if (airTemperature != MISSING amp;amp; quality.matches("[01459]")) {
System.out.println("Year " year " " airTemperature);
context.write(new Text(year), new TextPair(String.valueOf(airTemperature),1));
}
// Text Pair — пользовательский код типа данных ниже
public class TextPair implements WritableComparable<TextPair> {
private Text first;
private Text second;
//Default constructor is a must
public TextPair() {
this.first=new Text();
this.second=new Text();
}
public TextPair(String first,int second) {
try {
this.first=new Text(first);
this.second=new Text(String.valueOf(second));
}catch(Exception ex) {
System.out.println("Exception occurred " ex.getCause());
}
}
// Other methods such as compare, equals, hashcode, write, readFields etc implementation also needs to done
public Text getFirst() {
return first;
}
public Text getSecond() {
return second;
}
@Override
public String toString() {
return this.first "t" this.second "t";
}
}
Если вам нужна еще более подробная информация, обратитесь к Окончательному руководству Hadoop. Надеюсь, это поможет.
Комментарии:
1. Привет @Pushkin, я следовал указанной вами логике. Но я получаю ошибку того же типа. Я сослался на окончательный путеводитель. Но у меня это не работает.
2. Я получаю такую ошибку. Ошибка: java.io.IOException: несоответствие типа значению с карты: ожидаемый org.apache.hadoop.io.FloatWritable, получена текстовая пара
3. Я видел, как это происходило, когда в коде задания (где вы настраиваете mapper и reducer) тип вывода был указан иначе, чем тот, который фактически выводится из mapper. Также было бы полезно, если бы вы могли поделиться своим полным кодом для Job, Mapper и Reducer.
4. Это сработало отлично. И нам не нужно использовать TextPair в моем случае. Это можно сделать с самим текстом. Большое спасибо за вашу помощь.