stream.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 498 行 · 第 1/2 页

SCALA
498
字号
    /** The stream resulting from the concatenation of this stream with the argument stream.   *  @param rest   The stream that gets appended to this stream   */  override def append[B >: A](rest: => Iterable[B]): Stream[B] =    if (isEmpty) rest.toStream else Stream.cons(head, tail append rest)      /** An iterator returning the elements of this stream one by one.   */  override def elements: Iterator[A] = new Iterator[A] {    var current = Stream.this    def hasNext: Boolean = !current.isEmpty    def next: A = { val result = current.head; current = current.tail; result }  }  /** The stream without its last element.   *  @throws Predef.UnsupportedOperationException if the stream is empty.   */  def init: Stream[A] =    if (isEmpty) throw new UnsupportedOperationException("Stream.empty.init")    else if (tail.isEmpty) Stream.empty    else Stream.cons(head, tail.init)  /** Returns the last element of this stream.   *   *  @return the last element of the stream.   *  @throws Predef.NoSuchElementException if the stream is empty.   */  override final def last: A =    if (isEmpty) throw new NoSuchElementException("Stream.empty.last")    else       if (tail.isEmpty) head else tail.last  /** Returns the <code>n</code>-th element of this stream. The first element   *  (head of the stream) is at position 0.   *   *  @param n index of the element to return   *  @return  the element at position <code>n</code> in this stream.   *  @throws Predef.NoSuchElementException if the stream is too short.   */  override def apply(n: Int): A = drop(n).head  /** Returns the <code>n</code> first elements of this stream, or else the whole    *  stream, if it has less than <code>n</code> elements.   *   *  @param n the number of elements to take.   *  @return the <code>n</code> first elements of this stream.   */  override def take(n: Int): Stream[A] =    if (isEmpty || n <= 0) Stream.empty    else Stream.cons(head, if (n == 1) Stream.empty else (tail.take(n-1)))  /** Returns the stream without its <code>n</code> first elements.   *  If the stream has less than <code>n</code> elements, the empty stream is returned.   *   *  @param n the number of elements to drop.   *  @return the stream without its <code>n</code> first elements.   */  override final def drop(n: Int): Stream[A] = {    if (isEmpty || n <= 0) this    else tail.drop(n - 1)  }     /** Returns the longest prefix of this stream whose elements satisfy   *  the predicate <code>p</code>.   *   *  @param p the test predicate.   *  @return  the longest prefix of this stream whose elements satisfy   *           the predicate <code>p</code>.   */  override def takeWhile(p: A => Boolean): Stream[A] =    if (isEmpty || !p(head)) Stream.empty    else Stream.cons(head, tail takeWhile p)  /** Returns the longest suffix of this stream whose first element   *  does not satisfy the predicate <code>p</code>.   *   *  @param p the test predicate.   *  @return  the longest suffix of the stream whose first element   *           does not satisfy the predicate <code>p</code>.   */  override final def dropWhile(p: A => Boolean): Stream[A] = {    if (isEmpty || !p(head)) this    else tail.dropWhile(p)  }  /** Returns the stream resulting from applying the given function <code>f</code> to each   *  element of this stream.   *   *  @param f function to apply to each element.   *  @return <code>[f(a0), ..., f(an)]</code> if this stream is <code>[a0, ..., an]</code>.   */  override def map[B](f: A => B): Stream[B] =    if (isEmpty) Stream.empty    else Stream.cons(f(head), tail map f)  /** Apply the given function <code>f</code> to each element of this stream   *  (while respecting the order of the elements).   *   *  @param f the treatment to apply to each element.   */  override final def foreach(f: A => Unit) {    if (isEmpty) {}    else { f(head); tail.foreach(f) }  }  /** Returns all the elements of this stream that satisfy the   *  predicate <code>p</code>. The order of the elements is preserved.   *   *  @param p the predicate used to filter the stream.   *  @return the elements of this stream satisfying <code>p</code>.   */  override final def filter(p: A => Boolean): Stream[A] = {    if (isEmpty) this    else if (p(head)) Stream.cons(head, tail.filter(p))    else tail.filter(p)  }  /** Tests if the predicate <code>p</code> is satisfied by all elements   *  in this stream.   *   *  @param p the test predicate.   *  @return  <code>true</code> iff all elements of this stream satisfy the   *           predicate <code>p</code>.   */  override final def forall(p: A => Boolean): Boolean = {    if (isEmpty) true    else if (p(head)) tail.forall(p)    else false  }  /** Tests the existence in this stream of an element that satisfies the   *  predicate <code>p</code>.   *   *  @param p the test predicate.   *  @return  <code>true</code> iff there exists an element in this stream that   *           satisfies the predicate <code>p</code>.   */  override final def exists(p: A => Boolean): Boolean = {    if (isEmpty) false    else if (p(head)) true    else tail.exists(p)  }  /** Combines the elements of this stream together using the binary   *  function <code>f</code>, from left to right, and starting with   *  the value <code>z</code>.   *   *  @return <code>f(... (f(f(z, a<sub>0</sub>), a<sub>1</sub>) ...),   *          a<sub>n</sub>)</code> if the stream is   *          <code>[a<sub>0</sub>, a<sub>1</sub>, ..., a<sub>n</sub>]</code>.   */  override final def foldLeft[B](z: B)(f: (B, A) => B): B = {    if (isEmpty) z    else tail.foldLeft(f(z, head))(f)  }  /** Combines the elements of this stream together using the binary   *  function <code>f</code>, from rigth to left, and starting with   *  the value <code>z</code>.   *   *  @return <code>f(a<sub>0</sub>, f(a<sub>1</sub>, f(..., f(a<sub>n</sub>, z)...)))</code>   *          if the stream is <code>[a<sub>0</sub>, a1, ..., a<sub>n</sub>]</code>.   */  override def foldRight[B](z: B)(f: (A, B) => B): B =    if (isEmpty) z    else f(head, tail.foldRight(z)(f))  /** Applies the given function <code>f</code> to each element of   *  this stream, then concatenates the results.   *   *  @param f the function to apply on each element.   *  @return  <code>f(a<sub>0</sub>) ::: ... ::: f(a<sub>n</sub>)</code> if   *           this stream is <code>[a<sub>0</sub>, ..., a<sub>n</sub>]</code>.   */  override def flatMap[B](f: A => Iterable[B]): Stream[B] =    if (isEmpty) Stream.empty    else {      val s: Stream[B] = f(head) match {        case x: Stream[_] => x        case y: List[_]   => y.toStream        case z            => z.toList.toStream      }      s append (tail flatMap f)    }  override def toStream = this  /** A stream consisting of all elements of this stream in reverse order.   */  override def reverse: Stream[A] =    foldLeft(Stream.empty: Stream[A])((xs, x) => Stream.cons(x, xs))  /** Fills the given array <code>xs</code> with the elements of   *  this stream starting at position <code>start</code>.   *   *  @param  xs the array to fill.   *  @param  start starting index.   *  @pre    the array must be large enough to hold all elements.   */  override final def copyToArray[B >: A](xs: Array[B], start: Int) {    if (!isEmpty) { xs(start) = head; tail.copyToArray(xs, start + 1) }  }  /** Returns a stream formed from this stream and the specified stream   *  <code>that</code> by associating each element of the former with   *  the element at the same position in the latter.   *  If one of the two streams is longer than the other, its remaining elements are ignored.   *   *  @return     <code>Stream({a<sub>0</sub>,b<sub>0</sub>}, ...,   *              {a<sub>min(m,n)</sub>,b<sub>min(m,n)</sub>)}</code> when   *              <code>Stream(a<sub>0</sub>, ..., a<sub>m</sub>)   *              zip Stream(b<sub>0</sub>, ..., b<sub>n</sub>)</code> is invoked.   */  def zip[B](that: Stream[B]): Stream[(A, B)] =    if (this.isEmpty || that.isEmpty) Stream.empty    else Stream.cons((this.head, that.head), this.tail zip that.tail)    /** Returns a stream that pairs each element of this stream   *  with its index, counting from 0.   *   *  @return      the stream <code>Stream({a<sub>0</sub>,0}, {a<sub>0</sub>,1},...)</code>   *               where <code>a<sub>i</sub></code> are the elements of this stream.   */  def zipWithIndex: Stream[(A, Int)] =    zip(Stream.from(0))  /** Prints elements of this stream one by one, separated by commas */  def print { print(", ") }  /** Prints elements of this stream one by one, separated by <code>sep</code>   *  @param sep   The separator string printed between consecutive elements.    */  def print(sep: String) {    if (isEmpty) Console.println("Stream.empty")    else { Console.print(head); Console.print(sep); tail.print(sep) }  }  /** Converts stream to string */  override def toString =    "Stream(" + addDefinedElems(new StringBuilder(), "") + ")"  /** Write all elements of this string into given string builder */  protected def addDefinedElems(buf: StringBuilder, prefix: String): StringBuilder}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?