映射器在Hadoop中输入键值对

时间:2013-10-27 22:51:45

标签: hadoop mapreduce key-value

通常,我们以以下形式编写映射器:

public static class Map extends Mapper<**LongWritable**, Text, Text, IntWritable>

这里映射器的输入键值对是<LongWritable, Text> - 据我所知,当映射器获取输入数据时,它逐行通过 - 因此映射器的键表示行号 - 如果我错了,请纠正我。

我的问题是:如果我将mapper的输入键值对作为<Text, Text>,那么它会给出错误

 java.lang.ClassCastException: org.apache.hadoop.io.LongWritable cannot be cast to org.apache.hadoop.io.Text

将映射器的输入键值对赋予<LongWritable, Text>是否必须 - 如果是,那么为什么?如果没有那么错误的原因是什么?你能帮我理解错误的正确推理吗?

提前致谢。

3 个答案:

答案 0 :(得分:30)

映射器的输入取决于使用的是什么InputFormat。 InputFormat负责读取传入的数据并将其整形为Mapper期望的任何格式。默认的InputFormat是TextInputFormat,它扩展了FileInputFormat<LongWritable, Text>

如果不更改InputFormat,则使用具有与<LongWritable, Text>不同的键值类型签名的Mapper将导致此错误。如果您希望输入<Text, Text>,则必须选择合适的InputFormat。您可以在作业设置中设置InputFormat:

job.setInputFormatClass(MyInputFormat.class);

就像我说的那样,默认设置为TextInputFormat。

现在,假设您的输入数据是由逗号分隔的一系列以换行符分隔的记录:

  • “A,value1”
  • “B 1,值2”

如果希望映射器的输入键为(“A”,“value1”),(“B”,“value2”),则必须使用<Text, Text>实现自定义的InputFormat和RecordReader。签名。 幸运的是,这很简单。有an example here并且可能还有一些示例浮动在StackOverflow周围。

简而言之,添加一个扩展FileInputFormat<Text, Text>的类和一个扩展RecordReader<Text, Text>的类。覆盖FileInputFormat#getRecordReader方法,让它返回自定义RecordReader的实例。

然后,您必须实现所需的RecordReader逻辑。最简单的方法是在自定义RecordReader中创建LineRecordReader的实例,并将所有基本职责委托给此实例。在getCurrentKey和getCurrentValue方法中,您将通过调用LineRecordReader#getCurrentValue并在逗号上将其拆分来实现用于提取逗号分隔的Text内容的逻辑。

最后,将新的InputFormat设置为Job InputFormat,如上面第二段所示。

答案 1 :(得分:1)

在汤姆怀特的“Hadoop:The Difinitive Guide”一书中,我认为他对此有适当的答案(第197页):

“的TextInputFormat的 键,简单地说是文件中的偏移量,通常不是很好 有用。文件中的每一行通常是键值对,由分隔符分隔 例如制表符。例如,这是由...产生的输出 TextOutputFormat,Hadoop的默认值 输出格式。要正确解释这些文件, KeyValueTextInputFormat  是合适的。

您可以通过指定分隔符 key.value.separator.in.input.line  属性。它 默认情况下是制表符。“

答案 2 :(得分:-3)

映射器输入的键将始终为整数类型....映射器输入键表示行的偏移号。而值表示整条线...... 记录阅读器在第一个周期中读取一行。映射器的o / p可以是你想要的任何东西(它可以是(Text,Text)或(Text,IntWritable)或......)