java 8中的素数

时间:2017-06-05 10:28:39

标签: java java-8 primes

我试图在Java 8中编写一个简单的素数程序。下面是程序。我想减少isPrime()中的代码。是否有某些内容可以过滤从2n/2的元素,然后为n%i == 0应用过滤器,这会使isPrime无关紧要?

import static java.util.stream.Collectors.toList;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Stream1 {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 20);
        // Prime number 
        System.out.println(numbers.stream()
                             .filter(Stream1::isPrime)
                             .collect(toList()));
    }

    public static boolean isPrime(int number) {
        for (int i = 2; i <= number / 2; i++) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }
}

9 个答案:

答案 0 :(得分:16)

IntStream可用于生成整数流

public static boolean isPrime(int number) {
    return !IntStream.rangeClosed(2, number/2).anyMatch(i -> number%i == 0); 
}

public static boolean isPrime(int number) {
    return IntStream.rangeClosed(2, number/2).noneMatch(i -> number%i == 0);
}

答案 1 :(得分:4)

您的isPrime()效率低下。首先,你不需要除以任何大于2的偶数,因为初始除以2将捕获所有偶数非素数。其次,您在number / 2处终止循环,而不是效率更高的sqrt(number)

你可以用这样的方法重写你的方法:

public static boolean isPrime(int number) {

    // Even numbers
    if (number % 2 == 0) {
        return number == 2;
    }

    // Odd numbers
    int limit = (int)(0.1 + Math.sqrt(number));
    for (int i = 3; i <= limit; i += 2) {
        if (number % i == 0) {
            return false;
        }
    }
    return true;
}

Eratosthenes的筛子仍然会更有效率,但对于一个相对较小的问题,这可能是过度的。

答案 2 :(得分:2)

根据@rossum的建议,您可以使用着名的Sieve of Eratosthenes来实现这一目标,它将非常快速地计算素数。

$Servers = Get-Content C:\temp\Servers.txt

$objExcel=New-Object -ComObject Excel.Application
$objExcel.Visible=-1
$WorkBook=$objExcel.WorkBooks.Add()
$sheet=$workbook.worksheets.item(1)
$class = "win32_Share"
$infos = Invoke-Command -ComputerName $Servers -ScriptBlock { Get-ChildItem "V:\Service\*" -File -Include *.dll, *.ocx }
$infos | 
    Sort PSComputerName | 
    Select-Object  @{l='Name';e={$_.PSComputerName}},@{l='File Name';e={$_.Name}},@{label="File Version";expression={$_.versioninfo.fileversion}},@{label="Date";expression={$_.LastWriteTime}} |
    ConvertTo-CSV -Del "`t" |
    | Clip
$sheet.cells.item(1,1).PasteSpecial() | Out-Null

$sheet.Range("A1:D1").interior.colorindex = 43 
#Autofit columns when completed
$range = $sheet.usedRange
$range.EntireColumn.Autofit()

答案 3 :(得分:0)

您也可以使用谓词来实现所需的目标。

import java.util.Arrays;
import java.util.List;
import java.util.function.IntPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class PrimeUsingStream {

     public static boolean isPrime(int i) {
            IntPredicate isDivisible = index -> i % index == 0;
            return i > 1 && IntStream.range(2, i).noneMatch(isDivisible);
     }

     public static void main(String[] args) 
     {

        //System.out.println(printPrime(200));

         List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 20,23);
            // Prime number 
        System.out.println(numbers.stream()
                                 .filter(PrimeUsingStream::isPrime)
                                 .collect(Collectors.toList()));
     }

}

答案 4 :(得分:0)

您可以在以下测试中使用流:

@Test
public void generatePrimeNumberListByStream(){
    List<Integer> primeNumbers =
            IntStream
                    .range(2,30)
                    .filter(number -> IntStream.range(2,number)
                            .noneMatch(divider -> number % divider == 0))
                    .boxed()
                    .collect(Collectors.toList());
    assertThat(primeNumbers, contains(2,3,5,7,11,13, 17,19, 23, 29));
}

答案 5 :(得分:0)

您可以像这样使用算法Sieve of Eratosthenes

public static IntStream primes(int max) {
    IntStream primes = IntStream.range(2, max);
    IntFunction<IntPredicate> sieve = n -> i -> i == n || i % n != 0;
    primes = primes.filter(sieve.apply(2));
    for (int i = 3; i * i <= max; i += 2)
        primes = primes.filter(sieve.apply(i));
    return primes;
}

System.out.println(primes(100).count());    // -> 25
System.out.println(primes(1000).count());   // -> 168
System.out.println(primes(10000).count());  // -> 1229

答案 6 :(得分:0)

public static boolean isPrime(int i) {
    return i % 2 != 0 && IntStream.iterate(
            3, n -> n <= (int)(Math.sqrt(i)), n -> n + 2)
            .noneMatch(k->i%k==0);
}

iterate具有3个参数,类似于for循环,base是开始,第二个是停止条件,第三个是增量规则。 1和2已经是质数,所以我们从3开始,直到到达数字的平方根为止就停止了。这个想法是假设n是一个正整数n = pq,其中p和q是质数。假设p大于n的平方根且大于n的平方根。将这些不等式相乘得到p * q> sqrt n * sqrt n,这意味着pq> n。这与我们的假设n = pq矛盾。因此,我们可以得出结论:p小于等于sqrt n或q小于等于sqrt n。

n-> n <=(int)(Math.sqrt(i))

最后,只要不被2整除,我们就不需要检查偶数,因此我们只尝试第二个数字。

(n-> n + 2)

答案 7 :(得分:0)

Java8 +解决方案

public static boolean isPrime(long number) {
    return number>1 && LongStream.rangeClosed(2, number / 2).noneMatch(i -> number % i == 0);
}

需要排除1个!

素数(或素数)是大于1的自然数,它不是两个较小自然数的乘积。

https://en.wikipedia.org/wiki/Prime_number

答案 8 :(得分:0)

public static void main(String[] args) {
    List<Integer> list = IntStream.range(0, 100).filter(i -> isPrime(i)).boxed().collect(Collectors.toList());
    System.out.println(list);

}

static boolean isPrime(int number) {
    return number > 1 && IntStream.rangeClosed(2, number/2).noneMatch(i -> number % i == 0);
}