Sample Program provided to count number of elements from an array that are less than the specified value. Processing time taken by the program varies, using Java 8 forEach and stream takes more time for execution. Please explain if I should go with Java 8 features and if not which areas should it be avoided, additionally will parallelStream or multithreading with multi core processor help?
Code:
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();
}
Output:
345918
4
21509
4
29651234
4
2242999
4
Questions:
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?
Even using multithreading with concurrent.ExecutorService gave consistent results:
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