2016-07-08 2 views
1

Целью является просмотр списка, выполняющего будущую операцию над каждым элементом списка, а затем суммирование значений, возвращаемых этими будущими операциями.Сохранение суммы на основе будущих операций

Я пытаюсь использовать неизменяемые данные.

Что-то вроде этого:

list.foldRight(0)((obj,sum) => { 
    val c: Int = doFutureThing(obj) 
    c + sum // no good: c is a Future[Int] 
} 

ответ

2

Попробуйте использовать что-то вроде этого:

import scala.concurrent.duration.Duration 
import scala.concurrent.{Await, Future} 
import scala.concurrent.ExecutionContext.Implicits.global 

object Scratch { 
    def operation(i: Int): Future[Int] = { 
    Future.successful(i+1) 
    } 

    def main(args: Array[String]) { 
    val list = List(1,2,3,4) 
    val resultFuture = Future 
     .sequence(list.map(operation)) 
     .transform(list => list.foldLeft(0)((x, y) => x+y), t => t) 
    println(Await.result(resultFuture, Duration.Inf)) 
    } 
} 

Что происходит здесь:

  1. Ключевая идея заключается в Future.sequence. Это позволяет вам конвертировать сборку фьючерсов в будущее коллекции, а затем работать с этой коллекцией обычным способом. Поэтому мы используем его для упрощения нашей работы. Теперь у нас есть Future[List[Int]] вместо List[Future[Int]]
  2. Нанесите наш Future[List[Int]] на Future[Int] с использованием метода transform. Собственно, здесь мы можем использовать любые преобразования, которые мы хотим, не только подсчитывая сумму.
  3. Мы ждем результата от Future[Int] с использованием контекста выполнения неявное по умолчанию

Единственная проблема с таким подходом может возникнуть, если ваша коллекция источник чрезвычайно велик, поэтому он не может соответствовать вашей куче, и вы хотите применить операции когда достаточно Futures of Int готовы (при условии, что порядок операций не важен). Если вы хотите это сделать, ответ должен быть немного сложнее.

1

Если вы начинаете с коллекцией предметов ...

val li = List(2, 4, 7) // List[Int] 

..., а затем преобразовать его в коллекцию фьючерсов ...

import concurrent._ 
import concurrent.ExecutionContext.Implicits.global 
val lfi = li.map(doFutureThing) // List[Future[Int]] 

... затем вы можете уменьшите их до одного предмета в будущем.

val fi = Future.reduce(lfi)(_+_) // Future[Int] 
Смежные вопросы