Ich habe eine Scala-Klasse, die das Maximum eines Eingabetyps IN mit einem MR-Job in Apache Spark zurückgibt. Diese Klasse funktioniert gut, wenn ich es von Scala nennen und es funktioniert wie folgt:Aufruf des primären Konstruktors mit mehreren impliziten Parametern Aufruf von 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
Nun möchte Ich mag diese auch von Java aufrufbar machen, aber ich einige Schwierigkeiten, die mit der impliziten Parameter. Ich weiß, dass implizite Parameter übergeben werden können, indem sie an die Argumentliste in Java angehängt werden, aber die impliziten Parameter sind in Scala. Deshalb versuche ich folgendes zu tun:
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])
die dann von Java aufgerufen werden kann:
public static <T> TypedColumn<T, Double> max(MapFunction<T, Double> f) {
return new TypedMax<T, Double>(f).toColumn();
}
ich viele Permutationen vorbei in den implicits aus dem Hilfs Konstruktor versucht haben, mit implicity
implicit
und herumspielen mit Kommas und Klammern. Allerdings beschwert es sich immer, dass ev $ 1 und ev $ 2 nicht gefunden werden. Ich habe aber in den Parameter zu übergeben, da sonst Fehler es:
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])
Und wenn ich versuche:
def this(f: MapFunction[IN, T]) =
this(x => f.call(x))(T => Ordered[T], TypeTag[T])
Das Ergebnis ist:
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])
Was bin ich fehlt/Missverständnis? Danke!
Dank Olivier. Sie haben Recht: Ich kann TypeTag nicht realisieren. Ich versuche gerade, einen Wrapper darum zu schreiben, um das ganze Problem zu umgehen, aber selbst das funktioniert nicht. Hast du Vorschläge dazu? Klasse TypedMaxJava [IN, T] (f: MapFunction [IN, T]) { def typedMax: TypedColumn [IN, T] = { neu TypedMax [IN, T] (x => f.call (x))) (Bestellung [T], TypeTag [T]). ToColumn } } reicht leider nicht – ScrubS
Es gibt keinen sauberen Weg herum, 'TypeTags' werden materialisiert von scalac ... Wenn Sie im Voraus die Untermenge von kennen Unterstützte Typen, die Sie haben könnten ein 'Objekt TypeTagForJava {def ttInt = TypeTag [Int]; ...} '. Andernfalls müssen Sie zur Reflexion zurückfallen, die Spark sowieso https://github.com/apache/spark/blob/master/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst verwendet/ScalaReflection.scala – OlivierBlanvillain