scala的stream流

Scala的流的实现在Stream中。

主要用到的实现类是Cons类。

@SerialVersionUID(-602202424901551803L)
final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] {
  override def isEmpty = false
  override def head = hd
  @volatile private[this] var tlVal: Stream[A] = _
  @volatile private[this] var tlGen = tl _
  def tailDefined: Boolean = tlGen eq null
  override def tail: Stream[A] = {
    if (!tailDefined)
      synchronized {
        if (!tailDefined) {
          tlVal = tlGen()
          tlGen = null
        }
      }

    tlVal
  }
}

从这段代码中可以看出,一个有A类组成的Stream流中,构成的主要参数有两个,一个是流中第一个元素,也就是head,而另一个参数则是一个返回内容为A类的流的方法,将会被转换为函数保存。与此同时,又定义了一个函数tail,则是返回第二个参数方法返回的那个流。以上述一致,返回的流也只包含一个head(也就是流中的第二个元素),和一个产生流的方法。这也是scala中的流是无限的原因。

 

由此可以得出,scala的流中的数据都是只要调用,才会被产生,一开始只存在流的首部元素,和产生剩余流的一个方法。

 

关于流的操作以filter()为例子。

override def filter(p: A => Boolean): Stream[A] = {
  // optimization: drop leading prefix of elems for which f returns false
  // var rest = this dropWhile (!p(_)) - forget DRY principle - GC can't collect otherwise
  var rest = this
  while (!rest.isEmpty && !p(rest.head)) rest = rest.tail
  // private utility func to avoid `this` on stack (would be needed for the lazy arg)
  if (rest.nonEmpty) Stream.filteredTail(rest, p)
  else Stream.Empty
}

filter()函数在被流调用的时候,首先只会去尝试与已经存在的第一个元素进行判断,如果不符合filter的条件,那么将会调用流产生下一个流的函数来产生下一个流,直到新的流的第一个元素符合filter的条件停止循环,可是流中的数据并不是严格有序的,但是如果只在这里结束,并不能保证剩下的流的数据会被过滤,所以要保证剩下的流中的数据也会在产生后被filter进行过滤,这样的操作存在于filteredTail()函数中。

private[immutable] def filteredTail[A](stream: Stream[A], p: A => Boolean) = {
  cons(stream.head, stream.tail filter p)
}

在这里,之间会重新创建一个流,第一个元素不变,不同的是这里会把在创建新流的函数中加入刚刚的filter()函数,合并在一起作为新的创建流函数,之后每一个新产生的元素都会紧接着被调用filter()函数进行过滤。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值