2015-10-25 15 views
5

Come posso sostituire questo codice con nuova API Java Stream:Come generare IntStream utilizzando Java API flusso

int n = someFunction(); // n > 0 
for (int i = 3; i * i <= n; i += 2) 
    System.out.print(i); 

ho cercato di utilizzare IntStream.iterate(3, i -> i + 2), ma non posso aggiungere condizione di arresto.

Come ho capito, non posso usare il metodo .limit(int) qui.

Qualche idea?

risposta

5

Si potrebbe usare limit(int): si dovrà determinare quanti elementi stanno per essere compreso tra 3 e sqrt(n) a passi di 2. Non ci sono esattamente (sqrt(n) - 3)/2 + 1 elementi, quindi si potrebbe scrivere:

IntStream.iterate(3, i -> i + 2).limit((int) (Math.sqrt(n) - 3)/2 + 1); 

Detto che, si potrebbe anche creare un intervallo chiuso 3-sqrt(n) e filtrare i valori anche, in questo modo:

IntStream.rangeClosed(3, (int) Math.sqrt(n)).filter(i -> i % 2 > 0) 
+2

A quanto pare questo il problema verrà risolto in Java 9: ​​http: //stackoverflow.com/questions/20746429/limit-a-stream-by-a-predicate –

+2

La versione dell'intervallo offre anche un comportamento parallelo molto migliore (per due motivi; il limite parallelo è costoso e iterate() è un modo fondamentalmente sequenziale per generare una sorgente di streaming.) –

2

Usando il mio libero StreamEx biblioteca altre due soluzioni sono possi oltre a quelli proposti nella risposta @Tunaki.

  1. Utilizzando backport di takeWhile metodo che appare nel JDK-9:

    IntStream is = IntStreamEx.iterate(3, i -> i + 2).takeWhile(i -> i*i <= n); 
    
  2. Utilizzando tre argomenti IntStreamEx.rangeClosed che consente di specificare il passo:

    IntStream is = IntStreamEx.rangeClosed(3, (int) Math.sqrt(n), 2); 
    
Problemi correlati