我有一个映射器,其输出值设置为这样的接口:
public interface OutValue extends Writable {}
在映射期间,我使用此签名创建对象并发出它们:
public class OutRecord implements OutValue {}
我的映射器是这样的:
public class ExampleMapper extends
Mapper<LongWritable, Text, ExampleKey, OutValue > {}
但是我收到此错误:
java.io.IOException: Type mismatch in value from map: expected OutValue, recieved OutRecord
at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.java:850)
at org.apache.hadoop.mapred.MapTask$NewOutputCollector.write(MapTask.java:541)
at org.apache.hadoop.mapreduce.TaskInputOutputContext.write(TaskInputOutputContext.java:80)
所以我的第一个直觉是尝试像这样投射它:
context.write(key, (OutValue) record);
但是我仍然遇到同样的错误。这在我将映射器输出类型从 OutRecord 类更改为 OutValue 接口之前有效。我这样做的原因是我想从这个映射器发出许多类型的 OutRecord 类。
这可能吗?OutValue 必须是类而不是接口吗?
更新:
我挖掘了 Hadoop 0.20.205.0 的一些源代码,发现了这个:
public synchronized void collect(K key, V value, int partition) throws IOException {
...
if (value.getClass() != valClass) {
throw new IOException("Type mismatch in value from map: expected "
+ valClass.getName() + ", recieved "
+ value.getClass().getName());
}
所以他们使用的运行时检查需要类中的严格相等,他们不检查子类/接口等。当然这是一个常见的用例,有没有人尝试过这样做?