2011-12-18 6 views
1

として設定で定義されたクラスのサブクラスを放出するとき、私は3つの簡単なクラスている:私は受け付けておりますがHadoopの地図出力にIOException ouputを

public abstract class Container implements WritableComparable<Container> {} //empty 
public class WeightedEdge extends Container { ... } 
public class NodeWeightContainer extends Container { ... } 

地図相は、このような

JobConf createGraphPConf = new JobConf(new Configuration()); 
Job job = new Job(createGraphPConf); 
... 
createGraphPConf.setMapOutputValueClass(Container.class); 

として構成されていましたこのエラー:

java.io.IOException: Type mismatch in value from map: expected org.hadoop.test.data.util.Container, recieved org.hadoop.test.data.WeightedEdge 
at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.java:1018) 
at org.apache.hadoop.mapred.MapTask$OldOutputCollector.collect(MapTask.java:591) 
at org.hadoop.test.map.CreateGPMap.map(CreateGPMap.java:33) 
at org.hadoop.test.map.CreateGPMap.map(CreateGPMap.java:19) 
at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50) 
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:435) 
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:371) 
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:210) 

なぜ構成で定義されたクラスのサブクラスを返すことができないのですか? ?その周りに道がありますか?問題は、マップフェーズで2つの異なるオブジェクトタイプを発行する必要があることです。

答えて

2

HadoopはsetMapOutputValueClassで指定されたクラスタイプとMappersから受け取るタイプを明示的にチェックするため、コンフィグレーションで定義されたクラスのサブクラスを返すことはできません。

これは、マッパーから出すオブジェクトをシリアライズ/デシリアライズする必要があるためです。逆シリアル化を実行すると、setMapOutputValueClass呼び出しで指定された型の新しいオブジェクトが作成され、WriteableComparableインターフェイスのメソッドを使用して、新しく作成されたオブジェクトがデータで埋められます。あなたは、私が今日、同じ問題に直面したコンテナ非抽象クラスを定義し、


    public enum ELEM_TYPE { WE, WECONTAINER } 

    public class Container implements WritableComparable<Container> 
    { 
     ELEM_TYPE type; //actual element type - 
         // WeightedEdge or NodeWeightContainer 
     object value; 

     //WritableComparable implementation 
     // that casts value to the appropriate type 
    } 
    public class WeightedEdge { ... } 
    public class NodeWeightContainer { ... } 

2

内の実際のオブジェクトとそのタイプ識別子を置くことが異なるオブジェクトタイプを発することができるように

。この問題に対処するために使用できるWritableクラスorg.apache.hadoop.io.GenericWritableがあります。

public class Container extends GenericWritable { 

    private static Class[] CLASSES = { 
      WeightedEdge.class, 
      NodeWeightContainer.class, 
    }; 

    protected Class[] getTypes() { 
     return CLASSES; 
    } 

} 

public class WeightedEdge implemets Writable {...} 
public class NodeWeightContainer implements Writable {...} 

今、あなたはあなたのマッパーの出力値の型としてクラスContainerを使用することができます:あなたは、クラスを拡張し、抽象メソッドを実装する必要があります。

重要:実際のマップ出力クラス(WeightedEdgeおよびNodeWeightContainer)は、Writableインターフェイスを実装する必要があります。