作为将Java代码转换为Scala代码的努力的一部分,我需要将Java流Files.walk(Paths.get(ROOT))
转换为Scala。我无法通过Google搜索找到解决方案。 asScala
不会做到这一点。任何提示?
以下是相关代码:
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中的Stream<Path>
。
答案 0 :(得分:26)
有一种稍微好一点的方法,不需要here
提到的{0}提到的compat图层或实验2.11版功能基本上只使用迭代器:
import java.nio.file.{Files, Paths}
import scala.collection.JavaConverters._
Files.list(Paths.get(".")).iterator().asScala
答案 1 :(得分:10)
Java 8 Streams和Scala Streams在概念上是不同的东西; Java 8 Stream不是一个集合,因此通常的集合转换器不起作用。您可以使用scala-java8-compat(github)库向Java Streams添加toScala
方法:
import scala.compat.java8.StreamConverters._
import java.nio.file.{ Files, Path, Paths }
val scalaStream: Stream[Path] = Files.walk(Paths.get(".")).toScala[Stream]
你无法在Java中真正使用这种转换(Java-&gt; Scala),所以如果你必须从Java那里做到这一点,那么只需运行流并自己构建Scala Stream就更容易(但仍然很尴尬)(这就是前面提到的图书馆在幕后所做的事情:
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 Stream,因此您无法通过将其转换为Scala Stream获得延迟评估的好处,并且可能只是将其直接转换为Vector。如果您只想使用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在-Xexperimental
标志下对SAM类型进行了实验性支持。这将是非实验性的,在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] = java.util.stream.ReferencePipeline$2@589838eb
scala> Files.walk(Paths.get(".")).filter(Files.isExecutable)
res2: java.util.stream.Stream[java.nio.file.Path] = java.util.stream.ReferencePipeline$2@185d8b6
答案 2 :(得分:2)
从public int getLineNumberFor(String lastName) {
char c = lastName.charAt(0);
if (c >= 'A' && c <= 'M') {
return 1;
} else if (c >= 'N' && c <= 'Z') {
return 2;
}
return 0;
}
开始,标准库包括Scala 2.13
,该库提供Java到Scala的隐式流转换:
scala.jdk.StreamConverters
请注意import scala.jdk.StreamConverters.Ops._
val javaStream = Files.walk(Paths.get("."))
// javaStream: java.util.stream.Stream[java.nio.file.Path] = java.util.stream.ReferencePipeline$3@51b1d486
javaStream.toScala(LazyList)
// scala.collection.immutable.LazyList[java.nio.file.Path] = LazyList(?)
javaStream.toScala(Iterator)
// Iterator[java.nio.file.Path] = <iterator>
(而不是LazyList
)的使用,因为Stream
在Stream
中已重命名为LazyList
。