2016-07-12 38 views
9

Come parte di uno sforzo di conversione del codice Java per codice Scala, ho bisogno di convertire il flusso di Java Files.walk(Paths.get(ROOT)) alla Scala. Non riesco a trovare una soluzione googling. asScala non lo farà. Qualche suggerimento?come convertire un Java Stream per una Scala flusso

Quelle che seguono è il codice corrispondenti

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; 
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; 

import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Paths; 
import java.util.stream.Collectors; 

.... 
    Files.walk(Paths.get(ROOT)) 
      .filter(path -> !path.equals(Paths.get(ROOT))) 
      .map(path -> Paths.get(ROOT).relativize(path)) 
      .map(path -> linkTo(methodOn(FileUploadController.class).getFile(path.toString())).withRel(path.toString())) 
      .collect(Collectors.toList())) 

dove il tipo di ritorno Files.walk (Paths.get (PRINCIPALE)) è Flusso in Java.

+0

@NathanielFord forse c'è un tag per Java 8? –

+0

Di cosa hai veramente bisogno? In 2.12, puoi 'stream.filter (x => qualcosa)'. –

+0

@ som-snytt Ho bisogno di convertire il tipo di flusso Java prima di applicare il codice Scala. – TeeKai

risposta

6

Java 8 Stream e Scala Stream sono concetti concettualmente diversi; Java 8 Stream non è una raccolta, quindi il solito convertitore di raccolta non funzionerà. È possibile utilizzare il (github) libreria scala-java8-compat per aggiungere un metodo toScala a Java Streams:

import scala.compat.java8.StreamConverters._ 
import java.nio.file.{ Files, Path, Paths } 

val scalaStream: Stream[Path] = Files.walk(Paths.get(".")).toScala[Stream] 

non si può davvero usare questa conversione (Java-> Scala) da Java, quindi se avete a che fare questo da Java, è più facile (ma ancora scomodo) per eseguire solo il flusso e costruire la Scala flusso te stesso (che è ciò che la libreria di cui sopra sta facendo sotto il cofano):

import scala.collection.immutable.Stream$; 
import scala.collection.mutable.Builder; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.util.stream.Stream; 

final Stream<Path> stream = Files.walk(Paths.get(".")); 
final Builder<Path, scala.collection.immutable.Stream<Path>> builder = Stream$.MODULE$.newBuilder(); 
stream.forEachOrdered(builder::$plus$eq); 
final scala.collection.immutable.Stream<Path> result = builder.result(); 

Tuttavia, in entrambi i sensi sarà completamente consumare il Java Flusso, quindi non si ottiene il vantaggio della valutazione lenta convertendolo in un flusso di Scala e potrebbe anche solo c invertirlo direttamente in un vettore. Se si desidera semplicemente utilizzare la sintassi letterale della funzione Scala, esistono diversi modi per ottenere ciò. Si potrebbe utilizzare la stessa libreria di utilizzare convertitori di funzioni, simili ai convertitori di raccolta:

import scala.compat.java8.FunctionConverters._ 
import java.nio.file.{ Files, Path, Paths } 

val p: Path => Boolean = p => Files.isExecutable(p) 
val stream: java.util.stream.Stream[Path] = Files.walk(Paths.get(".")).filter(p.asJava) 

alternativa dal 2.11, Scala ha il supporto sperimentale per i tipi di SAM sotto la bandiera -Xexperimental. Questo non sarà sperimentale senza una bandiera in 2.12.

$ scala 
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92). 
Type in expressions for evaluation. Or try :help. 

scala> import java.nio.file.{ Files, Path, Paths } 
import java.nio.file.{Files, Path, Paths} 

scala> Files.walk(Paths.get(".")).filter(p => Files.isExecutable(p)) 
<console>:13: error: missing parameter type 
     Files.walk(Paths.get(".")).filter(p => Files.isExecutable(p)) 
             ^

scala> :set -Xexperimental 

scala> Files.walk(Paths.get(".")).filter(p => Files.isExecutable(p)) 
res1: java.util.stream.Stream[java.nio.file.Path] = [email protected] 

scala> Files.walk(Paths.get(".")).filter(Files.isExecutable) 
res2: java.util.stream.Stream[java.nio.file.Path] = [email protected] 
11

C'è un modo un po 'più bello, senza bisogno dello strato compat o sperimentali 2.11 caratteristiche di cui here da @marcospereira

Fondamentalmente basta usare un iteratore:

import java.nio.file.{Files, Paths} 
import scala.collection.JavaConverters._ 

Files.list(Paths.get(".")).iterator().asScala 
Problemi correlati