0

こんにちは、私は現在、Java Generics の問題に直面しています。使用する必要があるメソッドには、この署名があります

static<K1,V1,K2,V2> void addMapper(JobConf job, 
           Class<? extends Mapper<K1,V1,K2,V2>> klass, 
           Class<? extends K1> inputKeyClass, 
           Class<? extends V1> inputValueClass, 
           Class<? extends K2> outputKeyClass, 
           Class<? extends V2> outputValueClass, 
           boolean byValue, JobConf mapperConf) 

これが私がそれを呼ぶ方法です

ChainMapper.addMapper(conf, NameMapper.class, 
           Object.class, Object.class, Object.class, Object.class, 
           false, nameYearConf);

NameMapper は次のように定義されます。

public class NameMapper extends Mapper<Object, Object, Object, Object> { }

また、他の 2 つのパラメーターは正しく初期化されています

JobConf conf = new JobConf(); JobConf nameYearConf = new JobConf(false);

コンパイルしようとすると、次のエラーが発生します

    src\MeanYear.java:107: error: method addMapper in class ChainMapper cannot be applied to given types;
                    ChainMapper.addMapper(conf, NameMapper.class, Object.class,
                               ^
      required: JobConf,Class<? extends Mapper<K1,V1,K2,V2>>,Class<? extends K1>,Class<? extends V1>,Class<? extends K2>,Class<? extends V2>,boolean,JobConf
      found: JobConf,Class<MeanYear.NameMapper>,Class<Object>,Class<Object>,Class<Object>,Class<Object>,boolean,JobConf
      reason: no instance(s) of type variable(s) K1,V1,K2,V2 exist so that argument type Class<MeanYear.NameMapper> conforms to formal parameter type Class<? extends Mapper<K1,V1,K2,V2>>
      where K1,V1,K2,V2 are type-variables:
        K1 extends Object declared in method <K1,V1,K2,V2>addMapper(JobConf,Class<? extends Mapper<K1,V1,K2,V2>>,Class<? extends K1>,Class<? extends V1>,Class<? extends K2>,Class<? extends V2>,boolean,JobConf)
        V1 extends Object declared in method <K1,V1,K2,V2>addMapper(JobConf,Class<? extends Mapper<K1,V1,K2,V2>>,Class<? extends K1>,Class<? extends V1>,Class<? extends K2>,Class<? extends V2>,boolean,JobConf)
        K2 extends Object declared in method <K1,V1,K2,V2>addMapper(JobConf,Class<? extends Mapper<K1,V1,K2,V2>>,Class<? extends K1>,Class<? extends V1>,Class<? extends K2>,Class<? extends V2>,boolean,JobConf)
        V2 extends Object declared in method <K1,V1,K2,V2>addMapper(JobConf,Class<? extends Mapper<K1,V1,K2,V2>>,Class<? extends K1>,Class<? extends V1>,Class<? extends K2>,Class<? extends V2>,boolean,JobConf)

私は自分が間違っていることを本当に理解できません。いくつかの同様の例とコンパイルを試してみましたが、それらは機能します。ここで提供されているいくつかの例も試しましたが、成功しませんでした。ありがとう。

4

1 に答える 1

1

一見したところ、新しい API パッケージと古い API パッケージのクラスが混在していると思います。

ChainMapper(1.1.2 の時点で) は古い API パッケージに対してのみ実装(org.apache.hadoop.mapredされており、新しい API パッケージ ( ) には移植されていませんorg.apache.hadoop.mapreduce

そのため、ChainMapper.addMapper( Class<? extends Mapper<K1,V1,K2,V2>> klass) の 2 番目の引数は 型であることが期待されますorg.apache.hadoop.mapred.Mapper

現在のマッパーは Mapper クラスを拡張しているため、新しい API はインターフェースではなくクラスであるため、NameMapperこれは新しい API Mapper クラス ( ) であると私は信じています。org.apache.hadoop.mapreduce

NameMapperクラスの署名を古い API Mapper インターフェースの署名と一致するように修正することで修正できるはずです。

public class NameMapper extends MapReduceBase 
                        implements Mapper<Object, Object, Object, Object> { }

これは、現在のマップ メソッドのシグネチャを変更する必要があることも意味します。

protected void map(Object key, Object value, Context context) { }
// to
public void map(Object key, Object value, OutputCollector collector,
                Reporter reporter) { }

また、新しい Mapper API のセットアップ メソッドとクリーンアップ メソッドを使用している場合は、それらも置き換える必要があります。

public void close() { } // instead of cleanup(Context) {}
public void configure(JobConf conf) { } // instead of setup(Context) {}
于 2013-06-25T10:13:04.663 に答える