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 + -
显示快捷键?