Sum of a list of integers using Java 8

I just played with Java 8 and compared some things with Java 6, using a program to calculate the sum of even numbers in a large list

Java 8

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)));
        }
    }
}

Java 6

public class ListOperationsClassic {

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

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

        long start = System.currentTimeMillis();

        BigInteger sum = BigInteger.ZERO;

        for(BigInteger n : list) {
            if(n.mod(new BigInteger("2")).equals(BigInteger.ZERO))
                sum = sum.add(n);
        }

        System.out.println(sum);

        long end = System.currentTimeMillis();

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

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

I have two questions

  • In Java 8 code, I originally used mapToInt(BigInteger::intValue).sum())to decrease the value, but got a negative result -1795017296! What for? The expected result 2499950000 itself is within a range that can be expressed through int, as I understand it.
  • I ran the code several times, I always found the code in Java 8, taking 5 times more time than the code using Java 6. What can mean? For work on this scale, is it not worth using parallelStreamand / or is a reduceplain old for a loop better?

Here is one of the results:

2499950000
Time taken using Java 6: 52 ms

2499950000
Time taken using Java 8:  249 ms
+3
3

, JIT GC-ing . :

  • : 686
  • lamdbda: 681
  • : 405

, , - , lambdas, , BigIntegers long.
new 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);
    }
}
+6

: , Integer.MAX_VALUE, , , , , , Integer.MIN_VALUE. - .

, , , -, ? , , , , .

, , , :

  • Java 6: BigInteger sum .add().
  • Java 8: long, .

, parallelStream() , , , stream().

, , , , - JVM, ..

, 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());

reduce(), BinaryOperator<T>, BigInteger .

, , , , , Optional<T>.

, sum.isPresent(), , , , !list.isEmpty(), , , sum.get() .

, 1 :

  • Java 6: 190 ~ 210 .
  • Java 8 : 160 ~ 220 .
  • Java 8, : 180 ~ 260 .
  • Java 8, : 180 ~ 270 .

, , , , , .

+5

You can simply call the shortcut to add directly to bigdecimal, and not convert to long.

list.parallelStream()
.filter(n -> n.mod(new BigInteger("2")).equals(BigInteger.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add)
0
source

All Articles