出力値が次のようなインターフェイスに設定されているマッパーがあります。
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());
}
したがって、彼らが使用している実行時チェックは、クラス内で厳密な等価性を必要とし、サブクラス化/インターフェースなどをチェックしません。確かにこれは一般的なユースケースです。誰かがこれをやろうとしましたか?