有趣的地图和flatMap观察 - 未来,Scala

时间:2016-12-30 16:37:47

标签: scala

我注意到有关map,flatMap和Future的一些有趣行为,但我无法理解导致此行为的原因

//I have 3 Future objects. 

object ConcurrencyExample extends App {

  val time = System.currentTimeMillis()


 val future1 = Future{println("future1");1}
  val future2 = Future{println("future2");2}
  val future3 = Future{println("future3");3}

//I want to add 1,2 and 3. I can do it using flatMap

val result = future1 flatMap (f1=> future2.flatMap(f2 => future3.map(f3=> f3+f2+f1) ) )

result onComplete{
    case Success(v)=>println("result is "+v)
    case Failure(e) =>println("failed result:"+e)
  }


  Thread.sleep(1000)
}

结果

future2
future1
future3
result is 6

如果我将上面的代码更改为map,我会得到一个空的List()。我无法追踪这个空列表的来源?

val result = future1 map (f1=> future2.map(f2 => future3.map(f3=> f3+f2+f1) ) )

结果

future3
future2
future1
result is List()

如果我只使用两个Future对象和map,我得到Success(3)而不是一个空List()

val result = future1 map (f1=> future2.map(f2 => f2+f1) ) 

结果

future3
future2
future1
result is Success(3)

1 个答案:

答案 0 :(得分:2)

在第一种情况下,结果返回类型为Future[Int],在第二种情况下,结果返回类型为Future[Future[...]](某些嵌套的Future)

在第一种情况下执行

的onComplete
val result: Future[Int] = ???

result onComplete { println }

以上代码将返回Success(1)

在第二种情况下

val result: Future[Future[..]] = ???

result onComplete { println }

这可能会导致未评估的未来,这就是您看到List()的原因。请参阅下面的Scala repl输出。查看Future { Thread.sleep(1000); 1 }

的结果类型
scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global

scala> val f = Future { Thread.sleep(1000); 1 }
f: scala.concurrent.Future[Unit] = List()

scala> f onComplete { println }
Success(1)

<强>建议

了解flatMap和map之间的区别,知道何时使用flatMap和map。