toList

Materializa un iterable perezoso: tira de todos los valores y los recoge en una List.

List<A> toList<A>(Iterable<A> iterable) Future<List<A>> toListAsync<A>(FxAsyncIterable<A> iterable) List<T> Fx.toList() // chain Future<List<T>> FxAsync.toList()

Lección

toList es el operador terminal por excelencia: es lo que de verdad ejecuta una cadena que, hasta ese momento, no era más que un plan. Llamar a .toList() extrae en orden todos los valores que queden en el iterable y los recoge en una List<T> de verdad. Todo lo que hay aguas arriba —cada .map(), .filter(), .take()— solo se ejecuta porque toList pidió valores.

Eso también significa que toList es justo el operador que no debes llamar directamente sobre una fuente infinita o no acotada (range sin fin, cycle, repeat con un número enorme de repeticiones): intentará tirar de ella para siempre. Acótala primero con take(n) y luego llama a toList sobre el resultado acotado.

La versión asíncrona, toListAsync (o .toList() sobre una cadena FxAsync), espera cada elemento conforme lo extrae y devuelve un Future<List<T>>. Combinada con .concurrent(n) aguas arriba, las esperas individuales pueden solaparse aunque la lista final siga llegando en el orden original.

Demo 1 · Fundamentos & pereza

Fíjate en que map solo se ejecuta de verdad para los 3 valores que take(3) deja pasar — de entre un millón:

Demo 2 · Asíncrono, con concurrencia

.toList() sobre una cadena FxAsync espera cada elemento y te devuelve la lista entera de golpe; añade .concurrent(n) aguas arriba para solapar las esperas individuales:

Pruébalo tú

Ejercicio: materializa en una List los 4 primeros cuadrados de un rango enorme.

Relacionado: each — operador terminal para efectos secundarios en vez de una List · consume — operador terminal que descarta los resultados por completo · fx — la cadena que toList termina · concurrent — evaluación en paralelo