2017-05-27 17 views
1

Apache SparkでMRジョブを使用して入力INの最大値を返すScalaクラスがあります。複数の暗黙のパラメータを持つプライマリコンストラクタをJavaから呼び出す

// Class 
class TypedMax[IN, T](val f: IN => T)(implicit ev$1: T => Ordered[T], ev$2: TypeTag[T]) 
    extends Aggregator[IN, T, T] { 

    override def zero: T = null.asInstanceOf[T] 
    override def reduce(b: T, a: IN): T = if (b > f(a)) b else f(a) 
    override def merge(b1: T, b2: T): T = if (b1 > b2) b1 else b2 
    override def finish(reduction: T): T = reduction 
} 

// Call function 
def max[IN, T](f: IN => T)(implicit ev$1: T => Ordered[T], ev$2: TypeTag[T]): TypedColumn[IN, T] = 
    new TypedMax[IN, T](f).toColumn 

今、私はJavaからこれも呼び出し可能したいと思いますが、私は暗黙のパラメータに渡すといくつかの困難が生じています:私はスカラ座からそれを呼び出すと、次のようにそれが動作する場合は、このクラスでは正常に動作します。暗黙的なパラメータは、Javaの引数リストに追加することで渡すことができますが、暗黙的なパラメータはScalaにあります。したがって、私は、次の操作を実行しようとしています:

その後、Javaから呼び出すことができます
class TypedMax[IN, T](val f: IN => T)(implicit ev$1: T => Ordered[T], ev$2: TypeTag[T]) 
    extends Aggregator[IN, T, T] { 

    override def zero: T = null.asInstanceOf[T] 
    override def reduce(b: T, a: IN): T = if (b > f(a)) b else f(a) 
    override def merge(b1: T, b2: T): T = if (b1 > b2) b1 else b2 
    override def finish(reduction: T): T = reduction 

    // Java api support 
    def this(f: MapFunction[IN, java.lang.Double]) = 
    this(x => f.call(x).asInstanceOf[T])(ev$1: T => Ordered[T], ev$2: TypeTag[T]) 

public static <T> TypedColumn<T, Double> max(MapFunction<T, Double> f) { 
    return new TypedMax<T, Double>(f).toColumn(); 
} 

私はimplicityimplicitを使用して、補助コンストラクタから暗黙に渡すの多くの順列を試してみましたカンマとかっこで遊んでいます。しかし、それは常にev $ 1とev $ 2が見つからないと不平を言う。私がしようとした場合

Error:(135, 5) No implicit view available from T => Ordered[T]. 
    this(x => f.call(x).asInstanceOf[T]) 
Error:(135, 5) not enough arguments for constructor TypedMax: (implicit ev$1: T => Ordered[T], implicit ev$2: reflect.runtime.universe.TypeTag[T])org.apache.spark.sql.execution.aggregate.TypedMax[IN,T]. 
Unspecified value parameters ev$1, ev$2. 
    this(x => f.call(x).asInstanceOf[T]) 

そして:私はそれ以外の場合はエラーになりますので、しかし、パラメータを渡す必要があり

def this(f: MapFunction[IN, T]) = 
    this(x => f.call(x))(T => Ordered[T], TypeTag[T]) 

結果は次のとおりです。

Error:(135, 38) value Ordered of type scala.math.Ordered.type does not take type parameters. 
    this(x => f.call(x))(T => Ordered[T], TypeTag[T]) 
Error:(135, 50) missing argument list for method apply in object TypeTag 
Unapplied methods are only converted to functions when a function type is expected. 
You can make this conversion explicit by writing `apply _` or `apply(_,_)` instead of `apply`. 
    this(x => f.call(x))(T => Ordered[T], TypeTag[T]) 

私は何をしないのです/誤解? ありがとう!

答えて

1

T => Ordered[T]は、あなたが何と考えているのかを意味するものではなく、Tという文字列とscala.math.Ordered.apply[T]の引数を持つFunction1を作成しています。代わりに、次の試してみてください。

def this(f: MapFunction[IN, T], e: MapFunction[T, Ordered[T]], tt: TypeTag[T]) = 
    this(x => f.call(x))(x => e.call(x), tt) 

+0

おかげオリヴィエを(あなたがJavaからTypeTag[T]をマテリアライズすることができるようになるだろうしている場合、私は本当にわかりません)。そうです、私はタイプタグを実現できません。 私は現在、全体の問題を回避するために、その周りにラッパーを作成しようとしていますが、それでも動作していません。あなたはそれについて何か提案していますか? [入力、T](f:MapFunction [IN、T]){ def typedMax:TypedColumn [IN、T] = { 新しいTypedMax [IN、T](x => f.call(x) (Type [T]、TypeTag [T])を注文してください。toColumn } } 不幸にも不十分です – ScrubS

+0

クリーンな方法はありません、 'TypeTags'はscalacによって実現されています。サポートされている型は 'TypeTagForJava {def ttInt = TypeTag [Int]; ...} '。そうでなければ、リフレクションにフォールバックする必要があります。これはSparkが使用するものです。https://github.com/apache/spark/blob/master/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst /ScalaReflection.scala – OlivierBlanvillain

関連する問題