2015-11-08 18 views
6

È necessario eseguire alcune operazioni di sola lettura su tutti i file in una cartella in modo ricorsivo. Sto usando Files.walk per ottenere un flusso dei file, ma ho notato che l'API specifica che walk restituisce solo un flusso regolare, non un flusso parallelo.Come posso ottenere un flusso parallelo di Files.walk?

Come posso elaborare tutti i file in una directory in parallelo?

+4

Forse qualcosa come 'Files.walk (...). Parallel()'? – Flown

+0

@Flown Hah ... sciocco me. Non ti rendi conto che puoi convertire i normali flussi in parallelo. –

risposta

15

È possibile trasformare qualsiasi Stream in un parallelo Stream invocando Stream::parallel.

Stream<Path> stream = Files.walk(startPath).parallel().forEach(...); 
+9

Nota che 'Files.walk' si confronta in modo approssimato, specialmente se il sottoalbero ha meno di 1024 file. Se si ha molta elaborazione per file e non così tanti file, sarebbe probabilmente più efficiente per 'Files.walk (path) .collect (toList()). ParallelStream()'. –

+1

@TagirValeev Interessante. Hai un link che spiega perché è così? –

+7

@DavidGrinberg, codice sorgente JDK e benchmark. Usa 'Spliterators.spliteratorUnknownSize' internamente alla strategia di suddivisione per caricare blocchi in array che iniziano con 1024 elementi. Poiché la dimensione è sconosciuta, il motore di pipeline Stream presuppone che la divisione produca anche parti, ma in realtà non lo sono (la prima divisione per <= 1024 input esegue il dump di tutti gli elementi nel prefisso senza lasciare elementi per il suffisso). Ciò si traduce in prestazioni parallele molto male. –