2015-01-15 5 views
12

Ho una situazione in cui sto leggendo un database e restituendo un List<String>, in cui ogni stringa viene selezionata e aggiunta all'elenco in base ad alcuni criteri. La firma del metodo è:È sicuro per un metodo restituire un flusso <T>?

public List<String> myMethod(String query, int limit) 

il secondo parametro fornisce un limite superiore alla dimensione della lista restituita (impostazione limit=-1 rimuoverà alcuna limitazione dimensione). Per evitare di rendere questo metodo intensivo della memoria, ho scritto un metodo equivalente che restituisce Stream<String> invece di una lista. (Nota: Non ho bisogno di accesso casuale agli elementi restituiti o qualsiasi altra funzionalità specifiche per la lista.)

Tuttavia, io sono un po 'scettico su un ritorno Stream<>, soprattutto perché il metodo è pubblico. È sicuro che un metodo pubblico restituisca un valore Stream<> in Java?

+1

In alcune circostanze può essere più chiaro e più facile restituire un Iterable/Iterator. Io spesso costruisco un 'Iterator ' nel mio codice. Fare un 'Stream' da un' Iterator' è abbastanza [semplice] (http://stackoverflow.com/q/21956515/823393). – OldCurmudgeon

+2

@OldCurmudgeon Se si restituisce 'Stream', si ottiene' Iterator' quasi gratis ('stream.iterator()'). –

+0

@Marko - Concordato - ma sei ancora retrocompatibile con Java 7 e versioni precedenti se offri un semplice adattatore per lo streaming di 'Iterator' in Java 8. – OldCurmudgeon

risposta

12

Non solo è sicuro, è recommended dal capo architetto Java.

Soprattutto se i dati sono basati su I/O e quindi non ancora materializzati in memoria al momento in cui viene chiamato myMethod, sarebbe altamente consigliabile restituire un flusso anziché un elenco. Il cliente potrebbe aver bisogno di consumarne solo una parte o aggregarlo in alcuni dati di dimensioni fisse. Così hai la possibilità di passare dal requisito di memoria O (n) a O (1).

Si noti che se la parallelizzazione è anche un'idea interessante per il proprio caso d'uso, si consiglia di utilizzare uno splitteratore personalizzato il cui criterio di suddivisione è adattato alla natura sequenziale delle origini dati I/O. In questo caso posso consigliare a blog post of mine che presenta un tale splitterator.

+1

Grazie per il link alla risposta di Brian Goetz. Ho solo un dubbio sulla sicurezza: restituire un 'Stream <>' in un metodo pubblico significa che non posso garantire che verrà chiuso. Ho notato che il [Javadoc] (http://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html) dice "quasi tutte le istanze di streaming non hanno realmente bisogno di essere chiuse dopo usa ", ma non è stato in grado di trovare maggiori dettagli su quella parola sospetta" quasi ". –

+2

@ChthonicProject Bene, è molto semplice: se il tuo stream è supportato da una risorsa I/O, allora ha sicuramente bisogno di essere chiuso. Questa è una scelta che devi fare --- copiare tutto sull'heap, rilasciare la risorsa I/O o disporre di un flusso che deve essere chiuso. Ma vorrei discutere di quanto segue: è banale avere un metodo che converta in modo sicuro un flusso di I/O-backed in un elenco on-heap; l'altra direzione è impossibile. Quindi non aggiungi altro che flessibilità andando con il flusso. –

+1

Non ho notato la frase importante che segue nello stesso paragrafo nel Javadoc. Condivisi qui per diffondere la gioia: "* Se uno stream richiede la chiusura, può essere dichiarato come risorsa in un'istruzione try-with-resources. * Che, insieme al tuo commento (e, naturalmente, risposta principale), termina tutti i miei dubbi e le mie esitazioni. –

Problemi correlati