我正在尝试对Java
函数的两个不同实现进行基准测试,以检查数字是否包含至少一个偶数位。第一个实现使用手写循环,而第二个实现使用stream
。
public class StreamTest {
public boolean containsEvenDigit(int n) {
char [] digits = String.valueOf(n).toCharArray();
for(char d : digits) {
if(d % 2 == 0) {
return true;
}
}
return false;
}
public boolean containsEvenDigitStreams(int n) {
return String.valueOf(n).chars().anyMatch(i -> i % 2 == 0);
}
public static void main(String[] args) {
System.out.println("============WITHOUT STREAM============");
long start1 = System.nanoTime();
for(int i = 0 ; i < 1_000_000; i++) {
(new StreamTest()).containsEvenDigit(11215 + i);
}
long duration1 = (long)(System.nanoTime() - start1)/1_000_000;
System.out.println("Duration : " + duration1 + " milliseconds.");
System.out.println();
System.out.println("============USING STREAM============");
long start2 = System.nanoTime();
for(int i = 0 ; i < 1_000_000; i++) {
(new StreamTest()).containsEvenDigitStreams(11215 + i);
}
long duration2 = (long)(System.nanoTime() - start2)/1_000_000;
System.out.println("Duration : " + duration2 + " milliseconds.");
System.out.println();
}
}
在main
函数中,我没有输出正在测试的函数的返回值以消除I / O开销。结果表明,使用流的实现比使用循环的实现要慢得多。
============WITHOUT STREAM============
Duration : 119 milliseconds.
============USING STREAM============
Duration : 771 milliseconds.
这是否意味着Java
8个流比手写循环慢?
更新:我现在正在使用JMH对这两个功能进行基准测试。
public class MyBenchmark {
private boolean containsEvenDigit(int n) {
char [] digits = String.valueOf(n).toCharArray();
for(char d : digits) {
if(d % 2 == 0) {
return true;
}
}
return false;
}
private boolean containsEvenDigitStream(int n) {
return String.valueOf(n).chars().anyMatch(i -> i % 2 == 0);
}
@State(Scope.Thread)
public static class MyState{
public int x = 1_357_997_531;
}
@Benchmark
public void testLoop(MyState state, Blackhole blackhole) {
boolean retVal = containsEvenDigit(state.x);
blackhole.consume(retVal);
}
@Benchmark
public void testStream(MyState state, Blackhole blackhole) {
boolean retVal = containsEvenDigitStream(state.x);
blackhole.consume(retVal);
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
这次手写循环也以大约8的顺序击败了流。 这是结果摘要。
Benchmark Mode Cnt Score Error Units
MyBenchmark.testLoop thrpt 200 3578620.170 ± 207106.919 ops/s
MyBenchmark.testStream thrpt 200 433884.589 ± 23993.270 ops/s