Pro e contro se ritornare uno Stream o un Collection

Molte Java API hanno metodi che ritornano un Collection (eviterò di scrivere una Collection). Dalla versione 8 di Java è possibile restituire anche uno Stream. Dato che uno Stream è più flessibile ed efficiente in moti casi, le API che andremo a sviluppare dovrebbero restituire uno Stream o un Collection?

Un esempio significativo

Per restituire un Collection, gli elementi della collezione devono essere prima di tutto creati e poi caricati in memoria. Così ci sono due costi: computazionale e allocazione di memoria.

Consideriamo i seguenti due metodi dalla classe java.nio.file.Files:

static List   readAllLines(Path path)
static Stream  lines(Path path)

Per restituire una lista di stringhe, il metodo readAllLines()  deve prima leggereil file fino alla fine e poi salvare l’intero contenuto in memoria. D’altra parte, il metodo lines() restituisce immediatamente le righe lette appena inizia a leggere il file. I costi computazionali e di allocazione di memoria sono irrisori proprio grazie al vantaggio del comportamento lazy degli Stream in Java.

Per esempio, se è necessario cercare una qualsiasi occorrenzam il programma non deve leggere fino alla fine del file, ma solo fino alla prima occorrenza:

boolean result = Files.lines(path).anyMatch(x -> x.charAt(0) == 'z');

Perché uno Stream dovrebbe essere preferito nella maggior parte dei casi?

Le ragioni per cui è altamente consigliato restituire uno Stream nella maggior parte dei casi, risiedono in queste ragioni:

  1. se il risultato potrebbe essere infinito, andrebbe usato uno Stream.
  2. Se il risultato potrebbe essere molto grande, andrebbe usato uno Stream perché un Collection avrebbe un impatto maggiore sulle richieste di Heap Memory.
  3. Se il chiamante necessità soltanto di iterare la collezione (search, filter, aggregate), si dovrebbe usare uno Stream perché ha già tutti questi metodi implementati e inoltre perché non è necessario caricare tutta la collezione in memoria.
  4. Il Collection che hai scelto per mantenere i dati non è nella forma richiesta dal chiamante. Tornando uno Stream, il chiamante ha modo di richiamare a suo piacimento docollect(toCollection(factory)).
  5. Se sono necessari computazioni parallele (vedi parallelStream())

Questo articolo è tratto da alcune risposte su Stack Overflow ad un post di FredOverflow .

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *