2016-04-08 17 views
5

Ho una classe Scala Implicit dall'API RecordService, che volevo usare nel file Java.Come utilizzare la classe implicita di Scala in Java

package object spark { 

    implicit class RecordServiceContext(ctx: SparkContext) { 
    def recordServiceTextFile(path: String) : RDD[String] = { 
     new RecordServiceRDD(ctx).setPath(path) 
      .map(v => v(0).asInstanceOf[Text].toString) 
    } 
    } 

} 

Ora sto cercando di importare questo in un file Java utilizzando seguito di importazione.

import com.cloudera.recordservice.spark.*; 

ma io non sono in grado di utilizzare recordServiceTextFile ("percorso") da sparkContext.

In Scala l'importazione è leggermente diversa e funziona.

+1

non vedo una classe implicita. –

+0

L'importazione del codice Scala nel codice Java non è un'operazione banale ai miei occhi. Richiede una certa comprensione degli interni di javac. Anche la domanda non è chiara. Puoi essere un ma più chiaro sulla domanda? Più la domanda è "completa", migliore è la risposta. –

+0

@Ramesh Prego, ma non sono stato io. –

risposta

6

Ecco semplice definizione di classe implicita nel pacchetto di oggetti

package object spark { 
    implicit class Ext(param: Int) { 
    def a = param + 1 
    } 
} 

e ecco come si può utilizzare da Java

public class Test { 
    public static void main(String[] args) { 
     spark.package$.MODULE$.Ext(123).a(); 
    } 
} 

in modo da poter praticamente utilizzare RecordServiceContext come un metodo che avvolge la vostra SparkContext e aggiunge un metodo aggiuntivo che è possibile chiamare. Questa è l'ottimizzazione per le classi implicite.

Quello sarebbe qualcosa di simile:

SparkContext c = ??? 
RDD<String> rdd = com.cloudera.recordservice.spark.package$.MODULE$.RecordServiceContext(c) 
    .recordServiceTextFile("asdf"); 
+0

Grazie, funziona bene .. – Shankar

0
SparkContext ctx = ... 
RecordServiceContext rsct = new RecordServiceContext(ctx) 
recordServiceTextFile("/your_path") 
0

Questo dovrebbe farlo.

String s = new spark.RecordServiceContext("safa").recordServiceTextFile("dsf"); 

Ho cambiato le firme però.

classe

mio Scala si presenta così,

object spark { 
implicit class RecordServiceContext(ctx: String) { 
def recordServiceTextFile(path: String) : String = { 
"test" 
} 
} 
} 

La mia classe Java si presenta così,

public class TestScalaCall { 
public static void main(String args[]){ 
    String s = new spark.RecordServiceContext("safa").recordServiceTextFile("dsf"); 
} 
} 

Modifica ---

Quindi un rapido sguardo del cambiamento Scala chiede spettacoli us this.

In realtà stanno lavorando per rendere una classe definita in un package object comportarsi allo stesso modo della definizione all'interno di un normale package. Ma quello è designato per il rilascio ancora 2.12.

Quindi la raccomandazione che stanno dando è di conservare solo classi/oggetti assolutamente necessari che non necessitano di alcuna interazione esterna all'interno degli oggetti del pacchetto. Altrimenti, tienili sotto pacchetti regolari. Quindi per ora non è necessario utilizzare il costrutto package object.

Inoltre, un punto di pena riflettere "Ha davvero senso per definire qualcosa che è accessibile dall'esterno all'interno di un oggetto pacchetto?"

+0

la tua classe implicita manca 'pacchetto' prima di' oggetto spark', questo è il problema principale che sto affrontando ... – Shankar

+0

ho aggiunto la spiegazione nella risposta. Questo è qualcosa su cui il team di scala sta lavorando. –

1

Un package object spark viene compilato ad una classe package nel pacchetto spark. La classe implicita RecordServiceContext verrà compilata con un metodo statico RecordServiceContext (che è implicito def dello scala) in package e una classe package$RecordServiceContext.

Così il seguente codice dovrebbe farlo:

import com.cloudera.recordservice.spark.*; 

//some code 

RDD<String> rdd = package.RecordServiceContext(myContext).recordServiceTextFile(pathToFile); 

//some code 

Ma package è probabilmente una parola chiave riservata, e Java non ha modo di sfuggire loro per quanto ne so. Quindi dovrai fare un po 'di riflessione per invocare il metodo RecordServiceContext.

Problemi correlati