I was just playing around with Java 8 and comparing a few 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
mapToInt(BigInteger::intValue).sum())
to reduce the value , but
got a negative result -1795017296
! Why? The expected result 2499950000
itself is within the range that can be expressed by an int
as I
understand.parallelStream
and/or reduce
operations and plain old for loop
is better?Here are one of the results:
2499950000
Time taken using Java 6: 52 ms
2499950000
Time taken using Java 8: 249 ms
Here is my quick and dirty benchmark, allowing for JIT warm-up and GC-ing betwen each test. The results:
Note that I have modified your code to make the three tests as equivalent as possible - in particular, for lambdas, I'm using a reduction to add the BigIntegers instead of converting to long.
I have also removed the unnecessary creation of new BigInteger("2")
at each iteration.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With