2017-02-10 5 views
0

私はスーパー(親)クラスから継承するサブ(子)クラスを持っています。HadoopのMapperとReducerでサブクラスを提供する方法は?

のpublic staticクラスMyMapperがマッパー< ...、MyParentClassを拡張:私は子供と親の両方を提供できるように、私はこのような有効な値として、マッパーの入力値のための一般的な種類を提供するための方法をしたいです、...、...>

MyParentClassから拡張されたMyChildClassも有効にします。マップから値の

型の不一致:値は、私は例外取得しています子クラスであれば、私はプログラムを実行していますが

受け取っ期待MyParentClassを、MyChildClass

私はどのように有効にすることができます子クラスと親クラスの両方が有効な入出力であるの値をマッパーとの間で送受信しますか?

更新:

package hipi.examples.dumphib; 

import hipi.image.FloatImage; 
import hipi.image.ImageHeader; 
import hipi.imagebundle.mapreduce.ImageBundleInputFormat; 
import hipi.util.ByteUtils; 

import org.apache.hadoop.conf.Configuration; 
import org.apache.hadoop.conf.Configured; 
import org.apache.hadoop.fs.FileSystem; 
import org.apache.hadoop.fs.Path; 
import org.apache.hadoop.io.IntWritable; 
import org.apache.hadoop.io.Text; 
import org.apache.hadoop.mapreduce.Job; 
import org.apache.hadoop.mapreduce.Mapper; 
import org.apache.hadoop.mapreduce.Reducer; 
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 
import org.apache.hadoop.util.Tool; 
import org.apache.hadoop.util.ToolRunner; 

import java.io.IOException; 
import java.util.Iterator; 

public class DumpHib extends Configured implements Tool { 

    public static class DumpHibMapper extends Mapper<ImageHeader, FloatImage, IntWritable, Text> { 

    @Override 
    public void map(ImageHeader key, FloatImage value, Context context) throws IOException, InterruptedException { 

     int imageWidth = value.getWidth(); 
     int imageHeight = value.getHeight(); 

     String outputStr = null; 

     if (key == null) { 
    outputStr = "Failed to read image header."; 
     } else if (value == null) { 
    outputStr = "Failed to decode image data."; 
     } else { 
    String camera = key.getEXIFInformation("Model"); 
    String hexHash = ByteUtils.asHex(ByteUtils.FloatArraytoByteArray(value.getData())); 
    outputStr = imageWidth + "x" + imageHeight + "\t(" + hexHash + ")\t " + camera; 
     } 

     context.write(new IntWritable(1), new Text(outputStr)); 
    } 

    } 

    public static class DumpHibReducer extends Reducer<IntWritable, Text, IntWritable, Text> { 

    @Override 
    public void reduce(IntWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException { 
     for (Text value : values) { 
    context.write(key, value); 
     } 
    } 

    } 

    public int run(String[] args) throws Exception { 

    if (args.length < 2) { 
     System.out.println("Usage: dumphib <input HIB> <output directory>"); 
     System.exit(0); 
    } 

    Configuration conf = new Configuration(); 

    Job job = Job.getInstance(conf, "dumphib"); 

    job.setJarByClass(DumpHib.class); 
    job.setMapperClass(DumpHibMapper.class); 
    job.setReducerClass(DumpHibReducer.class); 

    job.setInputFormatClass(ImageBundleInputFormat.class); 
    job.setOutputKeyClass(IntWritable.class); 
    job.setOutputValueClass(Text.class); 

    String inputPath = args[0]; 
    String outputPath = args[1]; 

    removeDir(outputPath, conf); 

    FileInputFormat.setInputPaths(job, new Path(inputPath)); 
    FileOutputFormat.setOutputPath(job, new Path(outputPath)); 

    job.setNumReduceTasks(1); 

    return job.waitForCompletion(true) ? 0 : 1; 

    } 

    private static void removeDir(String path, Configuration conf) throws IOException { 
    Path output_path = new Path(path); 
    FileSystem fs = FileSystem.get(conf); 
    if (fs.exists(output_path)) { 
     fs.delete(output_path, true); 
    } 
    } 

    public static void main(String[] args) throws Exception { 
    int res = ToolRunner.run(new DumpHib(), args); 
    System.exit(res); 
    } 

} 

FloatImageは、スーパークラスであり、私はそれから延びChildFloatImageクラスを持っています。 ChildFloatImageがRecordReaderから返されると、前の例外がスローされます。このため

+0

可能であれば、マッパーコードを投稿してください。 – Amit

+0

@Amit上記のコードを確認できますか? "Text"クラスやそれを拡張する1つのクラスのような単純な型を使ってどのマッパーでもチェックすることができます。子クラスが返されると例外がスローされます。 –

+0

"?extends FloatImage"を汎用型定義として使用してみてください。また、私は以下の答えがGenericの型とその使い方を理解するのに役立つと思います。ジェネリックと継承の理解のためのもう1つのリソース - https://docs.oracle.com/javase/tutorial/java/generics/inheritance.html – Amit

答えて

0

は、私が続きますすべてを委譲するコンテナ/ラッパークラスを作成することですFloatImageContainer、あなたをこの場合、両方のFloatImageChildFloatImage

public static class MyMapper extends Mapper<..., FloatImageContainer, ..., ...> { 

にカプセル化することができます。

public class FloatImageContainer implements Writable, RawComparator<BinaryComparable> { 

    private FloatImage floatImage; 

    public FloatImage getFloatImage() { 
     return floatImage; 
    } 

    public void setFloatImage(FloatImage floatImage) { 
     this.floatImage = floatImage; 
    } 

    public FloatImageContainer() { 
     this.floatImage = new FloatImage(); 
    } 

    public FloatImageContainer(FloatImage floatImage) { 
     this.floatImage = floatImage; 
    } 

    @Override 
    public int compare(BinaryComparable o1, BinaryComparable o2) { 
     // TODO Auto-generated method stub 
     return floatImage.compare(o1, o2); 
    } 

    @Override 
    public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { 
     // TODO Auto-generated method stub 
     return floatImage.compare(b1, s1, l1, b2, s2, l2); 
    } 

    @Override 
    public void write(DataOutput out) throws IOException { 
     // TODO Auto-generated method stub 
     floatImage.write(out); 
    } 

    @Override 
    public void readFields(DataInput in) throws IOException { 
     // TODO Auto-generated method stub 
     floatImage.readFields(in); 
    } 

} 

をそしてマッパーで:origionalオブジェクトに必要な機能は次のよう直接使用されるクラスが1つしかないので、Hadoopの不都合の問題を取り除きます。FloatImageContainerこれは、親/子のいずれでもありません。

+0

これは最初の例ではうまく見え、マッパーの仕事を得ることができました。マッパーは、減速材のデータを喜んで書きます。しかし、追加のプロパティを持つ複数の子と子がある場合、デフォルトのコンストラクタはフィールドをレデューサーに読み戻すときにも機能しますか? Containerは、実行時にどの子があるのか​​分からないため、逆シリアル化プロセスでは、親のプロパティを読み戻し、子のプロパティを読み取れません。あなたの考えを教えてください? – gyan

0

背景

理由は、型消去があなたのMyMapperが実際に(Mapperのジェネリック型パラメータの点で)正しいタイプを拡張していることを確認(実行時に)それは不可能へのJavaになります。

Javaは基本的にコンパイルされます。

List<String> list = new ArrayList<String>(); 
list.add("Hi"); 
String x = list.get(0); 

List list = new ArrayList(); 
list.add("Hi"); 
String x = (String) list.get(0); 

クレジットにこの例では、hereを行きます。

だからあなたはJavaは、特定のAMapper<A, B, C, D>BCDを見たいMyMapper入力している - ことができない、実行時に。コンパイル時にそのチェックを強制する必要があります。java.lang.Class#asSubclass

を使用して、代わりにこれをやって

job.setMapperClass(DumpHibMapper.class); 

あなたは、すべてのカスタムサブクラスのために次の操作を行うことができソリューション

ソリューションを

job.setMapperClass(DumpHibMapper.class.asSubclass(Mapper.class)); 
+0

返信ありがとうございますが、実際には例外:「Mapからの値の型の不一致:予想されるFloatImage、受信したMyChildFloatImage」 は、「DumpHibMapper」ではなく「FloatImage」に関連しています。だから私は "DumpHibMapper"を修正すべきではないと思うのですが、 "FloatImage"に関連するIS-A(Child/parent)関係を受け入れるべきです。あなたは何をお奨めしますか? –

+0

私は以下のように答えました。 Pls。見てみましょう。 –

関連する問題