在Java8中
当我编写这样的代码时:
Stream<Integer> xs = Arrays.asList(1, 3, 5, 6, 7, 10).stream();
xs.map(x -> x * x).filter (x -> x > 15).forEach(System.out::println);Java8流分为两部分:中间操作和终端操作,其中-AFAIK -实际操作(底层迭代)是在终端ops中完成的,而每个中间操作附加了自己的-let me名称it- Apply内部类。
这样,列表上将只有一次迭代。
来自JDK8的示例代码:
@Override
@SuppressWarnings("unchecked")
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u));
}
};
}
};
}在斯卡拉
当我编写这样的代码时:
val xs = List(1, 3, 5, 6, 7, 10)
xs map (x => x * x) filter (x => x > 15) foreach (println)我已经阅读了一段时间,但我从未明确地听说过这样的术语,而且,SDK实现循环(使用递归或常规循环)在每个操作上都是这样的:
final override def map[B, That](f: A => B)(implicit bf: CanBuildFrom[List[A], B, That]): That = {
if (bf eq List.ReusableCBF) {
if (this eq Nil) Nil.asInstanceOf[That] else {
val h = new ::[B](f(head), Nil)
var t: ::[B] = h
var rest = tail
while (rest ne Nil) {
val nx = new ::(f(rest.head), Nil)
t.tl = nx
t = nx
rest = rest.tail
}
h.asInstanceOf[That]
}
}
else super.map(f)
}我的问题是:
我们能不能考虑一下,在同一件事情上的Java实现会更快。(O(n) in Java与O(倍数n) in Scala)
发布于 2015-07-28 00:54:25
Java 8流是Scala迭代器的特性较少的同义词,除了它们的并行计算能力外.
如果您不需要并行计算(而且大多数情况下,开销不值得-仅对于大型昂贵的任务才需要并行计算),那么您可以使用Scala中的.iterator (然后是to[Vector]或其他您想要的东西)进行相同的处理。
Java8流是手动专用的(Scala Iterator不是),所以有些用例它们要快得多,但这并不是因为在此过程中重新创建集合所产生的常数因素--至少,如果您在其中抛出一个.iterator。(如果没有.iterator,Scala集合在默认情况下会急切地进行评估;Java集合没有这个选项。)
您编写的Java 8代码的Scala等价物如下:
val xsi = Array(1, 3, 5, 6, 7, 10).iterator
xsi.map(x => x*x).filter(_ > 15).foreach(println)这里用Scala和Java.创建的集合数量没有区别。
对Scala的Iterator文档采用非常清晰的“终端操作”语言可能是个好主意。Java 8流文档很棒,因为它们使您在构建工作描述和最终完成工作时非常清晰。
Scala还提供了一个Stream类,它可以回溯旧工作(因此,如果要重用它,就不必第二次计算它),还提供了各种views,这样您就不必每次想要使用它时都要重新创建处理链。例如,用你的平方,你可以
val xsv = Array(1, 3, 5, 6, 7, 10).view
val xsq = xsv.map(x => x*x)
xsq.filter(_ > 15).foreach(println)
xsq.filter(_ < 5).foreach(println)然而,对于Java8流,xsq将在第一个终端操作之后耗尽。
因此Scala实际上完成了Java 8流所做的所有事情(除了并行性),而且还有更多,而且很长一段时间都是如此。
Scala也有并行化集合,但是Java 8实现在性能上有足够的优势,因此我建议首先使用它们。而且,如果手动专门化是您的专长,那么Java 8流具有Int、Double和Long的特性,这是性能上的一大胜利。(注意:使用asList的示例并不是手动专用的。)
但是,如果您只想对操作排队,而不需要构建中间集合的开销,Scala就会这样做。你只要问问就行了。
发布于 2015-07-27 23:31:28
Scala中的列表非常迫切,这意味着(正如您所说)列表上有多个迭代。(至少)有两种方法可以解决这个问题。
使用视图:
xs.view.map(x => x * x).filter(x => x > 15).force或者通过将列表转换为流(这是惰性的):
xs.toStream.map(x => x * x).filter(x => x > 15)https://stackoverflow.com/questions/31664918
复制相似问题