2016-07-12 2 views
9

В рамках усилий по преобразованию кода Java в код Scala мне нужно преобразовать поток Java Files.walk(Paths.get(ROOT)) в Scala. Я не могу найти решение по googling. asScala этого не сделает. Любые намеки?Как преобразовать поток Java в поток Scala

В нижеуказанных является соответствующий код:

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())) 

где Files.walk (Paths.get (ROOT)) Возвращаемый тип потока в Java.

+0

@NathanielFord может быть, есть тег для Java 8? –

+0

Что вам нужно? В 2.12 вы можете 'stream.filter (x => something)'. –

+0

@ som-snytt Мне нужно сначала преобразовать тип потока Java, прежде чем применять код Scala. – TeeKai

ответ

6

Java 8 Streams и Scala Streams концептуально разные вещи; Java 8 Stream не является коллекцией, поэтому обычный конвертер коллекции не будет работать. Вы можете использовать scala-java8-compat (github) библиотеку, чтобы добавить метод toScala к Java Streams:

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

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

Вы не можете использовать это преобразование (Java-> Scala) от Java, так что если вы должны сделать это из Java, это легче (но все-таки неудобно), чтобы просто запустить поток и построить Scala класс, сформированный с учетом способностей учащихся самостоятельно (что вышеупомянутая библиотека делает под капотом):

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(); 

Однако оба способа полностью потреблять Java Поток, поэтому вы не получаете преимущества от ленивой оценки, преобразовывая ее в поток Scala и, возможно, просто c переведите его прямо в вектор. Если вы просто хотите использовать синтаксис литерала функции Scala, существуют разные способы достижения этого. Вы можете использовать ту же библиотеку, чтобы использовать преобразователи функции, аналогичный преобразователи коллекции:

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) 

В качестве альтернативы, так как 2.11, Scala имеет экспериментальную поддержку типов SAM под -Xexperimental флага. Это будет не экспериментально без флага в 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

Существует немного лучше способ без необходимости в Compat слой или экспериментальные 2,11 функции, упомянутые here по @marcospereira

В основном просто использовать итератор:

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

Files.list(Paths.get(".")).iterator().asScala 
Смежные вопросы