toList
Materializa un iterable perezoso: tira de todos los valores y los recoge en una List.
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.
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