简体   繁体   中英

Java's Lambda Stream Filter Count is Slower than For and Foreach Loop

I am very interested in Java's new feature, Lambda. Besides giving concise and clear code, it also improve performance by using Stream and not creating objects.

I created a simple test to create a bunch of random numbers and then count how many of it is bigger than 49. I am surprised that the regular for and foreach loop gives better performance.

This is the code that I used:

    long numberOfData = 20000000;

    Random random = new Random();
    IntStream intStream = random.ints(0, 100);
    List<Integer> rand = intStream.limit(numberOfData)
                                  .boxed()
                                  .collect(Collectors.toList());

    // Iterate using "Lambda"
    OffsetTime startL = OffsetTime.now();

    long countL = rand.stream()
                    .filter(x -> x > 49)
                    .count();

    OffsetTime endL = OffsetTime.now();
    Duration durationL = Duration.between(startL, endL);

    System.out.println("[Lambda ] " + countL + " / " + numberOfData 
                     + " in " + durationL.toMillis() + "ms");

    // Iterate using "Foreach"
    int countFE = 0;
    OffsetTime startFE = OffsetTime.now();
    for (int aNumber : rand) {
        if (aNumber > 49) {
            countFE++;
        }
    }
    OffsetTime endFE = OffsetTime.now();
    Duration durationFE = Duration.between(startFE, endFE);
    System.out.println("[Foreach] " + countFE + " / " + numberOfData
                    +  " in " + durationFE.toMillis() + "ms");

    // Iterate using "For"
    int countF = 0;
    int maxLoop = rand.size();
    OffsetTime startF = OffsetTime.now();
    for (int i = 0; i < maxLoop; i++) {
        if (rand.get(i) > 49) {
            countF++;
        }
    }
    OffsetTime endF = OffsetTime.now();
    Duration durationF = Duration.between(startF, endF);
    System.out.println("[For    ] " + countF + " / " + numberOfData
                    + " in " + durationF.toMillis() + "ms");

First run result:

[Lambda ] 10002783 / 20000000 in 325ms
[Foreach] 10002783 / 20000000 in 296ms
[For    ] 10002783 / 20000000 in 195ms

Second run result (and so on is similar):

[Lambda ] 10000408 / 20000000 in 330ms
[Foreach] 10000408 / 20000000 in 304ms
[For    ] 10000408 / 20000000 in 202ms

Note: I am using JDK 1.8.0_11 running on Eclipse Luna 4.4.0 for Windows. All are 32-bits.


My questions are:

  1. Is there any wrong on my test?
  2. Does Lambda's stream only give benefits for operations involving many collections?

i think 2 problems: 1. it consumes a lot of time to compile IntPredicate. solution is declared IntPredicate out of filter function IntPredicate predicate=x -> x > 49; long countL = rand.stream() .filter(predicate) .count(); 2. the next problem is count() function is slow. but i don't know solution

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM