# 假设一个场景

 1 2 3 4 5 6 7 8 9  def randomList = (1 to 50).map(_ => Random.nextInt(100)).toList def isDivisibleBy3(n: Int) = { val isDivisible = n % 3 == 0 println(s"$n$isDivisible") isDivisible } randomList.filter(isDivisibleBy3).take(2) 

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52  scala> randomList.filter(isDivisibleBy3).take(2) 31 false 71 false 95 false 7 false 38 false 48 true 88 false 52 false 2 false 27 true 90 true 55 false 96 true 91 false 82 false 83 false 8 false 51 true 96 true 27 true 12 true 76 false 17 false 53 false 54 true 70 false 29 false 49 false 12 true 83 false 18 true 6 true 7 false 76 false 51 true 95 false 76 false 85 false 87 true 84 true 44 false 44 false 89 false 84 true 42 true 44 false 0 true 23 false 35 false 55 false res34: List[Int] = List(48, 27) 

# 现有解法的优缺点

 1  randomList.filter(isDivisibleBy3).take(2) 

# 试着解决其缺点

 1 2 3 4 5 6 7 8 9 10   def first2UsingMutable: List[Int] = { val result = ListBuffer[Int]() randomList.foreach(n => { if (isDivisibleBy3(n)) result.append(n) if (result.size == 2) return result.toList }) result.toList } 

 1 2 3 4 5 6 7  scala> first2UsingMutable 31 false 89 false 21 true 29 false 12 true res35: List[Int] = List(21, 12) 

 1 2 3 4 5 6 7   def first2UsingFold: List[Int] = { randomList.foldLeft(Nil: List[Int])((acc, n) => { if (acc.size == 2) return acc if (isDivisibleBy3(n)) n :: acc else acc }) } 

 1 2 3 4 5 6 7  scala> first2UsingFold 98 false 77 false 68 false 93 true 93 true res36: List[Int] = List(93, 93) 

# 如何保持代码的表意性而又不用做多余运算呢？

 1  randomList.toStream.filter(isDivisibleBy3).take(2).toList 

 1 2 3 4 5 6 7  scala> randomList.toStream.filter(isDivisibleBy3).take(2).toList 86 false 15 true 53 false 20 false 93 true res42: List[Int] = List(15, 93) 

# 实现原理

 1  MyStream(randomList: _*).filter(isDivisibleBy3).take(2).toList 

# 类型签名

 1 2 3 4 5 6 7  trait MyStream[+A] { . . . . . . } case object Empty extends MyStream[Nothing] case class Cons[+A](h: () => A, t: () => MyStream[A]) extends MyStream[A] 

# 初始化

 1  Cons(()=>1,()=>Cons(()=>2,()=>Empty)) 

# Smart初始化

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  object MyStream { def apply[A](elems: A*): MyStream[A] = { if (elems.isEmpty) empty else cons(elems.head, apply(elems.tail: _*)) } def cons[A](hd: => A, tl: => MyStream[A]): MyStream[A] = { lazy val head = hd lazy val tail = tl Cons(() => head, () => tail) } def empty[A]: MyStream[A] = Empty } 

 1  MyStream(randomList: _*).filter(isDivisibleBy3).take(2).toList 

# filter

 1 2 3 4 5 6 7 8 9 10 11 12 13 14  trait MyStream[+A] { def filter(p: A => Boolean): MyStream[A] = { this match { case Cons(h, t) => if (p(h())) cons(h(), t().filter(p)) else t().filter(p) case Empty => empty } } . . . . . . } 

 1  if (p(h())) cons(h(), t().filter(p)) 

# take

 1  MyStream(randomList: _*).filter(isDivisibleBy3).take(2) 

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  trait MyStream[+A] { . . . . . . def take(n: Int): MyStream[A] = { if (n > 0) this match { case Cons(h, t) if n == 1 => cons(h(), MyStream.empty) case Cons(h, t) => cons(h(), t().take(n - 1)) case _ => MyStream.empty } else MyStream() } . . . . . . } 

# toList

 1 2 3 4 5 6 7 8 9 10 11 12  trait MyStream[+A] { . . . . . . def toList: List[A] = { this match { case Cons(h, t) => h() :: t().toList case Empty => Nil } } } 

# 总结

• List(1,2,3)会构造一个容器，容器中包含数据
• List(1,2,3).filter(n=>n>1)会构造出一个新的容器，其中包含2和3，这两块具体的数据
• List(1,2,3).filter(n=>n>1).take(1)会把上一步中构造成的容器中的第一块数据取出，放入一个新容器

• MyStream(1,2,3)也会构造一个容器，但是这个容器中不包含数据，它包含能够生产数据的算法

• MyStream(1,2,3).filter(n=>n>1)也会构造出一个新的容器，这个容器中所包含的仍然是算法，是基于上一步构造出的能生产1，2，3的算法之上的判断数字是否大于1的算法
• MyStream(1,2,3).filter(n=>n>1).take(1)会把上一步中构造成的算法容器中的第一个算法取出，放入一个新容器
• MyStream(1,2,3).filter(n=>n>1).take(1).toList终于把上面所有步骤构造出的算法执行了，从而得到了最终想要的结果

posted on 2014-10-26 11:03  崔鹏飞  阅读(1229)  评论(0编辑  收藏  举报