使用Java 8功能需要更多时间

时间:2018-02-06 16:38:09

标签: multithreading lambda java-8 java-stream java.util.concurrent

提供的示例程序用于计算数组中小于指定值的元素数。 程序所花费的处理时间各不相同,使用Java 8 forEach和stream需要更多时间来执行。请解释一下我是否应该使用Java 8功能,如果没有应该避免哪些方面,还可以使用parallelStream或多核处理器来支持多核处理器吗?

代码:

public static void main(String[] args) {
    int lessThan = 4;

    // Using for loop iteration
    List<Integer> integerForSort1 = Arrays.asList(4, 1, 1, 2, 3);
    long startTime1 = System.nanoTime();
    long count1 = countNumbers(integerForSort1, lessThan);
    long stopTime1 = System.nanoTime();
    System.out.println(stopTime1 - startTime1);
    System.out.println(count1);
    integerForSort1 = null;
    System.gc();

    // Using binary search
    List<Integer> integerForSort2 = Arrays.asList(4, 1, 1, 2, 3);
    long startTime2 = System.nanoTime();
    long count2 = countByBinarySearch(integerForSort2, lessThan);
    long stopTime2 = System.nanoTime();
    System.out.println(stopTime2 - startTime2);
    System.out.println(count2);
    integerForSort2 = null;
    System.gc();

    // Using Java 8
    List<Integer> integerForSort3 = Arrays.asList(4, 1, 1, 2, 3);
    long startTime3 = System.nanoTime();
    long count3 = integerForSort3.stream()
            .filter(p -> p < lessThan)
            .count();
    long stopTime3 = System.nanoTime();
    System.out.println(stopTime3 - startTime3);
    System.out.println(count3);
    integerForSort3 = null;
    System.gc();

    //Using Java 8 for each loop
    List<Integer> integerForSort4 = Arrays.asList(4, 1, 1, 2, 3);
    long startTime4 = System.nanoTime();
    long count4 = process(integerForSort4, p -> p < lessThan);
    long stopTime4 = System.nanoTime();
    System.out.println(stopTime4 - startTime4);
    System.out.println(count4);
    integerForSort4 = null; 
}

public static long countNumbers(List<Integer> integerForSort, int lessThan) {
    long count = 0;
    Collections.sort(integerForSort);
    for (Integer anIntegerForSort : integerForSort) {
        if (anIntegerForSort < lessThan)
            count++;
    }
    return count;
}

public static long countByBinarySearch(List<Integer> integerForSort, int lessThan){
    if(integerForSort==null||integerForSort.isEmpty())
        return 0;
    int low = 0, mid = 0, high = integerForSort.size();
    Collections.sort(integerForSort);
    while(low != high){
        mid = (low + high) / 2;

        if (integerForSort.get(mid) < lessThan) {
            low = mid + 1;
        }
        else {
            high = mid;
        }
    }
    return low;
}    

public static long process(List<Integer> integerForSort, Predicate<Integer> predicate) {
    final AtomicInteger i = new AtomicInteger(0);
    integerForSort.forEach((Integer p) -> {
        if (predicate.test(p)) {
            i.getAndAdd(1);
        }
    });

    return i.intValue();
}

输出:

345918
4
21509
4
29651234
4
2242999
4

问题:

Is it possible to reduce the process time using Java 8 features?
Why does Java 8 stream takes more time?
How can I use lambda expression with binary Search, will it process faster?

即使对concurrent.ExecutorService使用多线程也能得到一致的结果:

Result 4 : Thread 'pool-1-thread-1' ran process - Using Java 8 stream in 6 millisecond, from 11:16:05:361 to 11:16:05:367
Result 4 : Thread 'pool-1-thread-2' ran process - Using Java 8 forEach in 3 millisecond, from 11:16:05:361 to 11:16:05:364
Result 4 : Thread 'pool-1-thread-4' ran process - Using Java 7 binary Search in 0 millisecond, from 11:16:05:379 to 11:16:05:379
Result 4 : Thread 'pool-1-thread-3' ran process - Using Java 7 for loop in 1 millisecond, from 11:16:05:362 to 11:16:05:363

1 个答案:

答案 0 :(得分:1)

我不知道答案,因为我没有进行任何测试,但我认为,5个元素的性能测试没有诊断价值,而且毫无意义。您应该生成10s,100s或数百mils的数组,以查看性能差异。

Java 8会创建多个对象,这会导致与简单for循环相反的开销。因此,只有5个测试元素,您的结果取决于初始化执行所需的工作量。

你知道,CPU上的5个数字相乘甚至比将其复制到GPU内存要快,所以即使在GPU开始计算之前你也可以在CPU上获得结果。但是如果你的数据增长并且你的GPU平行增加了数百个数字,你就会看到速度差异。