Stream

package stream

import Stream._
sealed trait Stream[+A] {

  def toList0: List[A] = this match {
    case Empty      => Nil
    case Cons(h, t) => h() :: t().toList0
  }

  def toList: List[A] = {
    @annotation.tailrec
    def loop(s: Stream[A], acc: List[A]): List[A] = s match {
      case Cons(h, t) => loop(t(), h() :: acc)
      case _          => acc
    }
    loop(this, Nil).reverse
  }

  def take(n: Int): Stream[A] = this match {
    case Cons(h, t) if n > 1  => cons(h(), t().take(n - 1))
    case Cons(h, _) if n == 1 => cons(h(), empty)
    case _                    => empty
  }

  @annotation.tailrec
  final def drop(n: Int): Stream[A] = this match {
    case Cons(_, t) if n > 0 => t().drop(n - 1)
    case _                   => this
  }

  def takeWhile(p: A => Boolean): Stream[A] = this match {
    case Cons(h, t) if (p(h())) => cons(h(), t().takeWhile(p))
    case _                      => empty
  }

  def foldRight[B](z: => B)(f: (A, => B) => B): B =
    this match {
      case Cons(h, t) => f(h(), t().foldRight(z)(f))
      case _          => z
    }

  def exists(p: A => Boolean): Boolean = foldRight(false)((a, b) => p(a) || b)

  def forAll(p: A => Boolean): Boolean = foldRight(true)((a, b) => p(a) && b)

  def takeWhileByFoldRight(p: A => Boolean): Stream[A] = foldRight(empty[A])((a, b) => if (p(a)) cons(a, b) else b)

  def headOption: Option[A] = foldRight(None: Option[A])((a, b) => Some(a))

  def map[B](f: A => B): Stream[B] = foldRight(empty[B])((a, b) => cons(f(a), b))

  def filter(f: A => Boolean): Stream[A] = foldRight(empty[A])((a, b) => if (f(a)) cons(a, b) else b)

  def append[B >: A](s: => Stream[B]): Stream[B] = foldRight(s)((a, b) => cons(a, b))

  def flatMap[B](f: A => Stream[B]): Stream[B] = foldRight(empty[B])((a, b) => f(a).append(b))

  def mapByUnfold[B](f: A => B): Stream[B] = unfold(this) {
    case Cons(h, t) => Some(f(h()), t())
    case _          => None
  }

  def takeByUnfold(n: Int): Stream[A] = unfold((n, this)) {
    case (i, Cons(h, t)) if i > 0 => Some((h(), (i - 1, t())))
    case _                        => None
  }

  def takeWhileByUnfold(f: A => Boolean): Stream[A] = unfold(this) {
    case Cons(h, t) if (f(h())) => Some((h(), t()))
    case _                      => None
  }

  def zipWith[B, C](s: Stream[B])(f: (A, B) => C): Stream[C] = unfold(this, s) {
    case (Cons(h1, t1), Cons(h2, t2)) => Some((f(h1(), h2()), (t1(), t2())))
    case _                            => None
  }

  def zipAll[B](s: Stream[B]): Stream[(Option[A], Option[B])] = unfold(this, s) {
    case (Empty, Empty)               => None
    case (Empty, Cons(h2, t2))        => Some((None, Some(h2())), (empty, t2()))
    case (Cons(h1, t1), Empty)        => Some((Some(h1()), None), (t1(), empty))
    case (Cons(h1, t1), Cons(h2, t2)) => Some((Some(h1()), Some(h2())), (t1(), t2()))
  }

  def tails: Stream[Stream[A]] =
    unfold(this) {
      case Empty => None
      case s     => Some((s, s drop 1))
    } append Stream(empty)

  def startsWith[A](s: Stream[A]): Boolean =
    zipAll(s).takeWhile(!_._2.isEmpty) forAll {
      case (h, h2) => h == h2
    }

  def hasSubsequence[A](s: Stream[A]): Boolean = tails exists (_ startsWith s)

  def scanRight[B](z: B)(f: (A, => B) => B): Stream[B] =
    foldRight((z, Stream(z)))((a, p0) => {
      lazy val p1 = p0
      val b2 = f(a, p1._1)
      (b2, cons(b2, p1._2))
    })._2
}

case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]

object Stream {

  def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
    lazy val head = hd
    lazy val tail = tl
    Cons(() => head, () => tail)
  }

  def empty[A]: Stream[A] = Empty

  def apply[A](as: A*): Stream[A] = if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))

  def constant[A](a: A): Stream[A] = Stream.cons(a, constant(a))

  def from(n: Int): Stream[Int] = Stream.cons(n, from(n + 1))

  def fibs(n: Int, n1: Int): Stream[Int] = Stream.cons(n, fibs(n1, n + n1))

  def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] = f(z) match {
    case Some((a, s)) => cons(a, unfold(s)(f))
    case _            => empty
  }

  def fromByUnfold(n: Int): Stream[Int] = unfold(n)(n => Some(n, n + 1))

  def constantByUnfold[A](a: A): Stream[A] = unfold(a)(a => Some(a, a))

  def onesByUnfold: Stream[Int] = unfold(1)(_ => Some(1, 1))
}

object Run {

  def main(args: Array[String]): Unit = {

    val s = Stream(1, 2, 3, 4, 5, 6, 7, 8, 9)

    println(s.toList0)
    println(s.toList)

    println(s.take(3))
    println(s.take(3).toList)

    println(s.drop(3))
    println(s.drop(3).toList)

    println(s.takeWhile(x => x < 5))
    println(s.takeWhile(x => x < 5).toList)

    println(s.forAll(_ % 1 == 0))
    println(s.forAll(_ % 2 == 0))

    println(s.takeWhileByFoldRight(_ % 2 == 0))
    println(s.takeWhileByFoldRight(_ % 2 == 0).toList)

    println(s.headOption)
    println(Stream().headOption)

    println(s.map(_ + 1))
    println(s.map(_ + 1).toList)

    println(s.filter(_ % 2 == 0))
    println(s.filter(_ % 2 == 0).toList)

    println(s.append(Stream(11, 12, 13, 14)))
    println(s.append(Stream(11, 12, 13, 14)).toList)

    println(s.flatMap(x => Stream(x + 100)))
    println(s.flatMap(x => Stream(x + 100)).toList)

    println(Stream.constant(12).take(10))
    println(Stream.constant(12).take(10).toList)

    println(Stream.from(12).take(10))
    println(Stream.from(12).take(10).toList)

    println(Stream.fibs(0, 1).take(10))
    println(Stream.fibs(0, 1).take(10).toList)

    println(Stream.unfold(0)(z => Some((z, z + 1))).take(10))
    println(Stream.unfold(0)(z => Some((z, z + 1))).take(10).toList)

    println(Stream.fromByUnfold(12).take(10))
    println(Stream.fromByUnfold(12).take(10).toList)

    println(Stream.constantByUnfold(12).take(10))
    println(Stream.constantByUnfold(12).take(10).toList)

    println(Stream.onesByUnfold.take(10))
    println(Stream.onesByUnfold.take(10).toList)

    println(s.mapByUnfold(_ + 1))
    println(s.mapByUnfold(_ + 1).toList)

    println(s.takeByUnfold(3))
    println(s.takeByUnfold(3).toList)

    println(s.takeWhileByUnfold(x => x < 5))
    println(s.takeWhileByUnfold(x => x < 5).toList)

    println(s.zipWith(Stream(11, 12, 13, 14, 15))(_ + _))
    println(s.zipWith(Stream(11, 12, 13, 14, 15))(_ + _).toList)

    println(s.zipAll(Stream(11, 12, 13, 14, 15)))
    println(s.zipAll(Stream(11, 12, 13, 14, 15)).toList)

    println(s.tails)
    println(s.tails.toList.map(_.toList))

    println(s.startsWith(Stream(1, 2, 3, 4, 5)))
    println(s.startsWith(Stream(1, 12, 3, 4, 5)))

    println(s.hasSubsequence(Stream(3, 4, 5)))
    println(s.hasSubsequence(Stream(3, 44, 5)))

    println(Stream(1, 2, 3).scanRight(0)(_ + _))
    println(Stream(1, 2, 3).scanRight(0)(_ + _).toList)
  }

}
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
Cons(<function0>,<function0>)
List(1, 2, 3)
Cons(<function0>,<function0>)
List(4, 5, 6, 7, 8, 9)
Cons(<function0>,<function0>)
List(1, 2, 3, 4)
true
false
Cons(<function0>,<function0>)
List(2, 4, 6, 8)
Some(1)
None
Cons(<function0>,<function0>)
List(2, 3, 4, 5, 6, 7, 8, 9, 10)
Cons(<function0>,<function0>)
List(2, 4, 6, 8)
Cons(<function0>,<function0>)
List(1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14)
Cons(<function0>,<function0>)
List(101, 102, 103, 104, 105, 106, 107, 108, 109)
Cons(<function0>,<function0>)
List(12, 12, 12, 12, 12, 12, 12, 12, 12, 12)
Cons(<function0>,<function0>)
List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Cons(<function0>,<function0>)
List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
Cons(<function0>,<function0>)
List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
Cons(<function0>,<function0>)
List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Cons(<function0>,<function0>)
List(12, 12, 12, 12, 12, 12, 12, 12, 12, 12)
Cons(<function0>,<function0>)
List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
Cons(<function0>,<function0>)
List(2, 3, 4, 5, 6, 7, 8, 9, 10)
Cons(<function0>,<function0>)
List(1, 2, 3)
Cons(<function0>,<function0>)
List(1, 2, 3, 4)
Cons(<function0>,<function0>)
List(12, 14, 16, 18, 20)
Cons(<function0>,<function0>)
List((Some(1),Some(11)), (Some(2),Some(12)), (Some(3),Some(13)), (Some(4),Some(14)), (Some(5),Some(15)), (Some(6),None), (Some(7),None), (Some(8),None), (Some(9),None))
Cons(<function0>,<function0>)
List(List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(2, 3, 4, 5, 6, 7, 8, 9), List(3, 4, 5, 6, 7, 8, 9), List(4, 5, 6, 7, 8, 9), List(5, 6, 7, 8, 9), List(6, 7, 8, 9), List(7, 8, 9), List(8, 9), List(9), List())
true
false
true
false
Cons(<function0>,<function0>)
List(6, 5, 3, 0)
时间: 2024-10-13 22:24:47

Stream的相关文章

爱你不容易 —— Stream详解

作为前端,我们常常会和 Stream 有着频繁的接触.比如使用 gulp 对项目进行构建的时候,我们会使用 gulp.src 接口将匹配到的文件转为 stream(流)的形式,再通过 .pipe() 接口对其进行链式加工处理: 或者比如我们通过 http 模块创建一个 HTTP 服务: const http = require('http'); http.createServer( (req, res) => { //... }).listen(3000); 此处的 req 和 res 也属于

XML Stream

package com.example.wangjiaxin20160516; import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;im

leetcode笔记:Find Median from Data Stream

一. 题目描述 Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. Examples: [2,3,4] , the median is 3 [2,3], the median is (2 + 3) / 2 = 2.5 De

【转】Scala 中的 Stream

///////////////////////////////////// def numsFrom(n: Int): Stream[Int] = n #:: numsFrom(n + 1) def testStream = { val tenOrMore = numsFrom(10) println(tenOrMore) println(tenOrMore.tail) println(tenOrMore.tail.tail) println(tenOrMore.tail.tail.tail)

Android4.4.4 GZIPOutputStream报错:Stream error

在android 4.4.4 机器上使用网友提供的GZipUtils方法进行GZip压缩,但是会一直报错Stream error.错误位置: public static void compress(InputStream is, OutputStream os) throws Exception { GZIPOutputStream gos = new GZIPOutputStream(os); int count; byte data[] = new byte[BUFFER]; while (

Java学习记录(补充八:Date类;Java流(Stream),文件(File)和IO)

Date类,Calendar类package Box1; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Random; //Date类 public class DateTest { public static void main(String[] args) { Date

Java 8 : Stream API 练习

//店铺属性类 public class Property { String name; // 距离,单位:米 Integer distance; // 销量,月售 Integer sales; // 价格,这里简单起见就写一个级别代表价格段 Integer priceLevel; public Property(String name, int distance, int sales, int priceLevel) { this.name = name; this.distance = di

浅谈PipelineDB系列一: Stream数据是如何写到Continuous View中的

PipelineDB Version:0.9.7 PostgreSQL Version:9.5.3 PipelineDB的数据处理组件: 从上图来看主要就是pipeline_streams,stream_fdw,Continuous View,Transform. 其实就是运用了Postgres的FDW功能来实现的stream功能. 从数据库也能看到这个FDW pipeline=# \des List of foreign servers Name | Owner | Foreign-data

InputStream只能读取一次的解决办法 C# byte[] 和Stream转换

x 情景--->>> 导入文件的时候,前台传过来一个文件, 后台接到: HttpPostedFileBase file = Request.Files[0];由于对这个文件后台处理比较多,读取里面的内容,还要将其转换为Stream写入一个新的文件...以前的做法是↓↓ 新建一个MemoryStream实例进行操作>>> Stream stream = new MemoryStream(); file.InputStream.Seek(0, SeekOrigin.Begi

C#之stream

在C#中经常要用stream stream下面主要有 FileStream:使用文件作为后备设备. BufferedStream:使用缓冲区作为后备设备,用来增强性能的中间存储. MemoryStream:使用内存作为后备存储,执行I/O速度快. NetworkStream:没有后备设备,用于在网络上传输数据. CryptoStream:和其他流配合使用,执行加密/解密操作. Stream类的常用方法: Seek()方法:设置流的当前位置. Read()方法和ReadByte()方法,对流执行同