13

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

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>- 如果是,那么为什么?如果没有,那么错误的原因是什么?你能帮我理解错误的正确原因吗?

提前致谢。

4

3 回答 3

32

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

如果不更改 InputFormat,使用具有不同 Key-Value 类型签名的 Mapper<LongWritable, Text>将导致此错误。如果您希望<Text, Text>输入,则必须选择适当的 InputFormat。您可以在 Job setup 中设置 InputFormat:

job.setInputFormatClass(MyInputFormat.class);

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

现在,假设您的输入数据是一堆用逗号分隔的换行符分隔记录:

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

如果您希望映射器的输入键为 ("A", "value1"), ("B", "value2"),则必须使用<Text, Text>签名实现自定义 InputFormat 和 RecordReader。幸运的是,这很容易。这里有一个例子,可能还有一些例子漂浮在 StackOverflow 周围。

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

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

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

于 2013-10-27T23:29:28.823 回答
1

在 Tom White 的“Hadoop:Difinitive Guide”一书中,我认为他对此有一个适当的答案(第 197 页):

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

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

于 2015-09-27T01:48:45.870 回答
-3

映射器输入的键将始终是整数类型....映射器输入键表示行的偏移量。并且值表示整行......记录阅读器在第一个循环中读取单行。映射器的 o/p 可以是任何你想要的(它可以是 (Text,Text) 或 (Text, IntWritable) 或......)

于 2016-01-08T10:31:43.377 回答