2016-06-14 36 views
5

ho scritto il seguente codice per ottenere tutti i numeri primi da 2..ncalcolo numeri primi (corsi d'acqua e lambda)

private static LongStream getPrimesStream(long number) { 
    return LongStream.range(2, number + 1) 
      .filter(PrimeStreamTest::isPrime); 
} 

private static boolean isPrime(final long number) { 
    return number == 2 || (number % 2 != 0 && LongStream 
      .range(2, (long) Math.ceil(Math.sqrt(number + 1))) 
      .filter(n -> n % 2 != 0) 
      .noneMatch(divisor -> number % divisor == 0) 
    ); 
} 

ho ottimizzato che controllando nella gamma di 2..sqrt (n) e filtrando i numeri pari, ma ora voglio ottimizzarlo ulteriormente memorizzando tutti i numeri primi precedentemente trovati (non mi interessa la memoria), in modo da poter filtrare i numeri divisibili da quei numeri primi, e non solo quelli divisibili da 2. So che ci sono soluzioni migliori, ma è solo un esercizio su lambda e torrenti.

+0

credo che la migliore ottimizzazione è quello di (a) passaggio da noneMatch() per AnyMatch() e nega il risultato (b) L'operazione di filtro che hai è davvero molto limitata a verificare se il numero nell'intervallo tra 2..sqrt (input) è divisibile per 2 e non controlla altri numeri primi come 3,5 .... Invece di tutti questi passaggi, lo stream torna non appena il numero è divisibile per il 2,3,4,5, .... – Baski

+2

@Baski: perché pensi che passare da 'noneMatch()' a 'anyMatch()' e negare il risultato ottimizzi qualcosa? – Holger

+2

Se si desidera ottimizzare la velocità al costo della memoria, implementare il setaccio di Eratostene usando un 'BitSet'. Ma, dato che questo è un esercizio in streaming, puoi usare 'getPrimesStream' in' isPrime' per ottenere i fattori primi da testare: 'return number == 2 || getPrimesStream ((long) ceil (sqrt (numero))). noneMatch (divisore -> numero% divisore == 0); ' – Misha

risposta

3

ma ora voglio di ottimizzare ulteriormente memorizzando tutti precedentemente trovato i numeri primi

Dal momento che richiederebbe la memorizzazione di questi valori nel mezzo del torrente gasdotto, vale a dire essere un'operazione intermedia e più streaming intermedio le operazioni dovrebbero essere apolidi in base ai loro documenti che stai cercando di utilizzare lo strumento sbagliato per il lavoro qui.

ops stateful possono essere implementati estraendo un flusso di Spliterator, avvolgendolo in uno personalizzato e riconfezionamento in un nuovo flusso, ma in questo caso che sembra difficilmente appropriata considerando che questo sarebbe essenzialmente tutto ciò che la vostra pipeline di flusso fa.

Dal momento che si sta cercando di eseguire un'attività calcolo stateful e parallelizzabile si potrebbe desiderare di esaminare la fork-join framework o CompletableFuture invece. Il primo viene anche utilizzato come parte dell'implementazione del flusso parallelo e quest'ultimo facilita la composizione dei calcoli e i relativi risultati.

1

provare questo

public static boolean isPrime(final long number) { 
    return LongStream.range(2,(long) Math.ceil(Math.sqrt(number + 1))).noneMatch(x -> number % x == 0); 
} 
+0

Posso sapere perché numero + 1? –

+0

@JigarNaik Potrei sbagliarmi. L'ho fatto solo per evitare errori di arrotondamento. – dehasi

+0

Perché non chiamare noneMatch() invece di anyMatch() e un segno di negazione? –