Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java 8对整数列表求和_Java_Biginteger_Java 8 - Fatal编程技术网

使用Java 8对整数列表求和

使用Java 8对整数列表求和,java,biginteger,java-8,Java,Biginteger,Java 8,我只是在玩Java8,并使用一个程序来计算一个大列表中偶数的总和,将一些东西与Java6进行比较 Java8 public class ListOperationsJava8 { static List<BigInteger> list = new LinkedList<>(); public static void main(String[] args) { createList(); long start = Sy

我只是在玩Java8,并使用一个程序来计算一个大列表中偶数的总和,将一些东西与Java6进行比较

Java8

public class ListOperationsJava8 {

    static List<BigInteger> list = new LinkedList<>();

    public static void main(String[] args) {
        createList();

        long start = System.currentTimeMillis();

        /*System.out.println(list.parallelStream().
                filter(n -> n.mod(new BigInteger("2")).equals(BigInteger.ZERO)).
                        mapToInt(BigInteger::intValue).sum());  --> gives result        -1795017296 */

        System.out.println(list.parallelStream().
                filter(n -> n.mod(new BigInteger("2")).equals(BigInteger.ZERO)).
                    mapToLong(BigInteger::longValue).sum());

        long end = System.currentTimeMillis();

        System.out.println("Time taken using Java 8:  " + (end - start) + " ms");
    }

    private static void createList() {
        for (int i = 0; i < 100000; i++) {
            list.add(new BigInteger(String.valueOf(i)));
        }
    }
}

对于第一个问题:您的值可能大于
Integer.MAX\u value
,因此溢出,这意味着它将在外部表示为从
Integer.MIN\u value
开始溢出是此处的关键字

对于第二部分,我不知道它到底为什么不同,可能最终可以在字节码中找到,但这真的是一个问题,还是一个过早优化的案例?如果是第一种情况,那么你应该担心,如果是第二种情况,那么你不应该注意它变慢了

但我从您的代码中观察到的一个区别是:

  • Java 6:使用一个
    biginger sum
    ,并对其调用
    .add()
    方法
  • Java8:使用一些
    long
    变量,并在内部将该变量添加到
另外,这里使用的是一个
parallelStream()
来进行非常快速的计算,这可能会导致一个问题,即创建新的底层线程实际上比使用普通的线性
stream()
要花费更多的时间

此外,如果您真的在测量速度,那么您应该做更多的测试,而不是每个测试用例运行一次,时间也可能取决于其他因素——JVM、CPU的时钟速度等等

最后一次编辑时,您的Java 8代码实际上并不代表您的Java 6代码,它应该是:

final BigInteger sum = BigInteger.ZERO;
list.stream()
.filter(n -> n.mod(new BigInteger("2")).equals(BigInteger.ZERO))
.forEach(n -> { sum = sum.add(n); });
要想完整地表示您的Java 6代码,请注意,
sum
的引入在这里并不是一件好事,如果您将它用于并行计算,那么这段代码根本不起作用

最后一次编辑是为了正确显示在Java 8中应该如何操作,它看起来是正确的,适用于并行版本,甚至可能在线性版本中获得额外的性能:

    Optional<BigInteger> sum = list.stream()
            .filter(n -> n.mod(new BigInteger("2")).equals(BigInteger.ZERO))
            .reduce((n1, n2) -> n1.add(n2));
    System.out.println(sum.get());
Optional sum=list.stream()
.filter(n->n.mod(新的BigInteger(“2”)).equals(BigInteger.ZERO))
.减少((n1,n2)->n1.添加(n2));
System.out.println(sum.get());
这里我使用
reduce()
运算符,它将
BinaryOperator
作为参数,我使用它将
BigInteger
添加到一起

需要注意的一点是,流可能是空的,因此它不知道是否有值,因此它返回一个
可选的

请仔细注意,通常您需要调用
sum.isPresent()
来检查它是否实际有值,但在这里我们知道必须有一个值作为
!list.isEmpty()
,因此我们直接调用
sum.get()

最后,我在我的电脑上测试了100万个数字的不同版本:

  • Java6:大约190~210ms
  • Java8您的代码:大约160~220ms
  • Java 8,矿井线性:大约180~260ms
  • Java 8,水雷并行:大约180~270ms

因此,由于这并不是真正正确的微基准测试,我认为结论是,你在这种情况下使用什么并不重要。

这是我的快速而肮脏的基准测试,允许在每次测试之间进行JIT预热和GC校准。结果是:

2499950000
Time taken using Java 6: 52 ms

2499950000
Time taken using Java 8:  249 ms
  • 循环频率:686毫秒
  • lamdbda:681毫秒
  • 平行λ:405毫秒
请注意,我已经修改了您的代码,使这三个测试尽可能等效-特别是对于lambdas,我使用了一个缩减来添加大整数,而不是转换为长整数。
我还删除了在每次迭代中不必要地创建新的BigInteger(“2”)

public class Test1 {

    static List<BigInteger> list = new LinkedList<>();
    static BigInteger TWO = new BigInteger("2");

    public static void main(String[] args) {
        createList();

        long sum = 0;

        //warm-up
        for (int i = 0; i < 100; i++) {
            sum += forLoop().longValue();
            sum += lambda().longValue();
            sum += parallelLambda().longValue();
        }

        {
            System.gc();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) sum += forLoop().longValue();
            long end = System.currentTimeMillis();
            System.out.println("Time taken using for loop:  " + (end - start) + " ms");
        }

        {
            System.gc();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) sum += lambda().longValue();
            long end = System.currentTimeMillis();
            System.out.println("Time taken using lambda:  " + (end - start) + " ms");
        }

        {
            System.gc();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) sum += parallelLambda().longValue();
            long end = System.currentTimeMillis();
            System.out.println("Time taken using parallelLambda:  " + (end - start) + " ms");
        }
    }

    private static void createList() {
        for (int i = 0; i < 100000; i++) {
            list.add(new BigInteger(String.valueOf(i)));
        }
    }

    private static BigInteger forLoop() {
        BigInteger sum = BigInteger.ZERO;

        for(BigInteger n : list) {
            if(n.mod(TWO).equals(BigInteger.ZERO))
                sum = sum.add(n);
        }
        return sum;
    }

    private static BigInteger lambda() {
        return list.stream().
                filter(n -> n.mod(TWO).equals(ZERO)).
                reduce(ZERO, BigInteger::add);
    }

    private static BigInteger parallelLambda() {
        return list.parallelStream().
                filter(n -> n.mod(TWO).equals(ZERO)).
                reduce(ZERO, BigInteger::add);
    }
}
公共类Test1{
静态列表=新建LinkedList();
静态BigInteger二=新的BigInteger(“2”);
公共静态void main(字符串[]args){
createList();
长和=0;
//热身
对于(int i=0;i<100;i++){
sum+=forLoop().longValue();
sum+=lambda().longValue();
sum+=parallelLambda().longValue();
}
{
gc();
长启动=System.currentTimeMillis();
对于(int i=0;i<100;i++)sum+=forLoop().longValue();
long end=System.currentTimeMillis();
println(“使用for循环所花费的时间:”+(结束-开始)+“毫秒”);
}
{
gc();
长启动=System.currentTimeMillis();
对于(int i=0;i<100;i++)sum+=lambda().longValue();
long end=System.currentTimeMillis();
System.out.println(“使用lambda所花费的时间:”+(结束-开始)+“毫秒”);
}
{
gc();
长启动=System.currentTimeMillis();
对于(int i=0;i<100;i++)和+=parallelLambda().longValue();
long end=System.currentTimeMillis();
System.out.println(“使用parallelLambda所花费的时间:”+(结束-开始)+“毫秒”);
}
}
私有静态void createList(){
对于(int i=0;i<100000;i++){
添加(新的biginger(String.valueOf(i));
}
}
私有静态BigInteger forLoop(){
BigInteger总和=BigInteger.0;
for(biginger n:list){
if(n.mod(2).equals(BigInteger.ZERO))
总和=总和。加(n);
}
回报金额;
}
私有静态BigInteger lambda(){
返回list.stream()。
过滤器(n->n.mod(两个).equals(零))。
reduce(零,BigInteger::add);
}
私有静态BigInteger并行lambda(){
返回list.parallelStream()。
过滤器(n->n.mod(两个).equals(零))。
reduce(零,BigInteger::add);
}
}
您只需
public class Test1 {

    static List<BigInteger> list = new LinkedList<>();
    static BigInteger TWO = new BigInteger("2");

    public static void main(String[] args) {
        createList();

        long sum = 0;

        //warm-up
        for (int i = 0; i < 100; i++) {
            sum += forLoop().longValue();
            sum += lambda().longValue();
            sum += parallelLambda().longValue();
        }

        {
            System.gc();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) sum += forLoop().longValue();
            long end = System.currentTimeMillis();
            System.out.println("Time taken using for loop:  " + (end - start) + " ms");
        }

        {
            System.gc();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) sum += lambda().longValue();
            long end = System.currentTimeMillis();
            System.out.println("Time taken using lambda:  " + (end - start) + " ms");
        }

        {
            System.gc();
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) sum += parallelLambda().longValue();
            long end = System.currentTimeMillis();
            System.out.println("Time taken using parallelLambda:  " + (end - start) + " ms");
        }
    }

    private static void createList() {
        for (int i = 0; i < 100000; i++) {
            list.add(new BigInteger(String.valueOf(i)));
        }
    }

    private static BigInteger forLoop() {
        BigInteger sum = BigInteger.ZERO;

        for(BigInteger n : list) {
            if(n.mod(TWO).equals(BigInteger.ZERO))
                sum = sum.add(n);
        }
        return sum;
    }

    private static BigInteger lambda() {
        return list.stream().
                filter(n -> n.mod(TWO).equals(ZERO)).
                reduce(ZERO, BigInteger::add);
    }

    private static BigInteger parallelLambda() {
        return list.parallelStream().
                filter(n -> n.mod(TWO).equals(ZERO)).
                reduce(ZERO, BigInteger::add);
    }
}
list.parallelStream()
.filter(n -> n.mod(new BigInteger("2")).equals(BigInteger.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add)