scala 输入流_Scala流的记忆化

scala 输入流

我了解了scala在内部使用Streams记忆的困难方式。

这是我第一次尝试解决欧拉问题5

def from(n: Int): Stream[Int] = n #:: from(n + 1)

def isDivisibleByRange(n: Int, r: Range) = {
  r.forall(n % _ == 0)
}

val a = from(21)
val o = a.find(isDivisibleByRange(_, Range(2, 21)))
o match {
  case Some(i) => println(i)
  case None => println("Nothing found!")
}

我对这个代码为什么会抛出OutOfMemoryError感到有些迷惑,这要归功于Stackoverflow ,因为对这个问题的答案是非常高的232792560,该范围内的所有整数都会在流的不同节点内存储,因此这个问题。

这实际上很容易看到,让我首先修改流生成器函数的副作用:

def from(n: Int): Stream[Int] = {println(s"Gen $n"); n #:: from(n + 1)}
val s = from(1)
s.take(10).toList 
s.take(10).toList

第二条语句不会打印任何内容。

鉴于这种记忆行为,有一些可能的修复方法,最简单的方法是在任何地方都不保留对流头的引用,而使用迭代器的find方法:

from(1).iterator.find(isDivisibleByRange(_, Range(1, 21)))

值得一提的是,Java 8流并没有被记住,而使用Java 8流的解决方案(可以大幅度地改进)如下:

@Test
public void testStreamOfInts() {
 Stream<Integer> intStream = Stream.generate(from(1));
 List<Integer> upto20 = IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());
 Predicate<Integer> p = (i -> isDivisibleOverRange(i, upto20));
 Optional<Integer> o = intStream.filter(p).findFirst();
 o.ifPresent(i -> System.out.println("Found: " + i));
}

private Supplier<Integer> from(Integer i) {
 AtomicInteger counter = new AtomicInteger(0);
 return () ->  counter.incrementAndGet();
}

private boolean isDivisibleOverRange(Integer n, List<Integer> l) {
 return l.stream().allMatch(i -> n % i == 0);
}

翻译自: https://www.javacodegeeks.com/2014/04/memoization-of-scala-streams.html

scala 输入流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值