2016-06-14 22 views
5

napisałem poniższy kod, żeby uzyskać wszystkie liczby pierwsze z 2..nobliczania liczb pierwszych (strumienie i 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) 
    ); 
} 

ja go zoptymalizowany poprzez sprawdzenie w zakresie 2..sqrt (n) i filtrowanie liczb parzystych, ale teraz chcę ją jeszcze bardziej zoptymalizować, przechowując wszystkie poprzednio znalezione liczby pierwsze (nie dbam o pamięć), tak, że mogę odfiltrować liczby podzielne przez te liczby pierwsze, a nie tylko te, które są podzielne przez 2. Wiem, że są lepsze rozwiązania, ale to tylko ćwiczenie na lambdach i strumieniach.

+0

Uważam, że lepiej optymalizacji jest do: (a) zmianę z noneMatch(), aby anyMatch() i neguje wynik (b) Działanie filtra masz naprawdę bardzo ogranicza się do sprawdzenia, czy liczba w zakresie od 2. sqrt (wejście) jest podzielna przez 2 i nie sprawdza innych liczb pierwszych, np. 3,5 .... Zamiast wszystkich tych kroków, strumień powraca, gdy tylko liczba jest podzielna przez 2,3,4,5, ... – Baski

+2

@Baski: dlaczego myślisz, że przejście z 'noneMatch()' na 'anyMatch()' i zanegowanie wyniku zoptymalizuje cokolwiek? – Holger

+2

Jeśli chcesz zoptymalizować prędkość za cenę pamięci, użyj sita Eratostenesa używając 'BitSet'. Ale ponieważ jest to ćwiczenie w strumieniach, możesz użyć 'getPrimesStream' wewnątrz' isPrime', aby sprawdzić czynniki pierwotne przed: 'return number == 2 || getPrimesStream ((long) ceil (sqrt (number))) noneMatch (dzielnik -> numer% dzielnik == 0); ' – Misha

Odpowiedz

3

ale teraz chcę dalej zoptymalizować go poprzez przechowywanie wszystkich poprzednio znalezionych liczb pierwszych

Od tego będzie wymagać przechowywania tych wartości w środku rurociągu strumienia, czyli być działanie pośrednie i najbardziej strumień pośredni Operacje powinny być bezpaństwowcami, zgodnie z ich dokumentami, do których próbujesz użyć niewłaściwego narzędzia do pracy tutaj.

Opcjonalne operacje stanowe można wdrożyć, wyodrębniając strumień Spliterator, zawijając go w niestandardowy i zmieniając go w nowy strumień, ale w tym przypadku wydaje się to mało odpowiednie, biorąc pod uwagę, że zasadniczo jest to wszystko, co robi potok strumienia.

Ponieważ próbujesz uruchomić stanowe i parallelizable zadanie obliczeniową warto zajrzeć do fork-join framework lub CompletableFuture zamiast. Ten pierwszy jest również wykorzystywany jako część implementacji strumienia równoległego, a drugi ułatwia kompozycję obliczeń i ich wyniki.

1

spróbować

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

Czy mogę wiedzieć, dlaczego numer +1? –

+0

@JigarNaik Mogę się mylić. Zrobiłem to tylko po to, aby uniknąć błędów zaokrąglania. – dehasi

+0

Dlaczego nie wywołać noneMatch() zamiast anyMatch() i znaku negacji? –