Table of Contents
ToggleDifference Between Optional orElse and orElseGet in Java
有兩個方法,可能會引起混淆, orElse 與 orElseGet ,如果值存在,則傳回值,不存在時,則傳回其他, orElse 傳入參數為泛型 T , orElseGet 傳入參數則為 Supplier 的功能接口, Difference Between Optional orElseGet and orElse in Java 本篇增加了範例,並透過單元測試來驗證產出結果。
public T orElse(T other) {
}
public T orElseGet(Supplier<? extends T> other) {
}
檔案目錄
./
+- src
+- test
| +- org
| +- ruoxue
| +- java_147
| +- optional
| +- DifferenceOptionalOrElseOrElseGetTest.java
單元測試
Difference Between Optional orElse and orElseGet 提供 orElse 、 orElseGet 等操作。
static
初始化靜態類別,提供隨機數、預設值 List 。
private static SecureRandom secureRandom = null;
public static final String SHA1PRNG = "SHA1PRNG";
public static List<String> defaultValues = Arrays.asList("DEFAULT_Beef", "DEFAULT_Chicken", "DEFAULT_Duck");
static {
new Static();
}
protected static class Static {
public Static() {
try {
secureRandom = SecureRandom.getInstance(SHA1PRNG);
secureRandom.setSeed(System.nanoTime());
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
orElse
Difference Between Optional orElse and orElseGet 建立 Optional 容器,取得容器內的值,若值為 Null 則傳回預設值,值如果存在,一樣會調用 getDefaultValue 方法,比較沒有效率。
public static String getDefaultValue() {
System.out.println("Call getDefaultValue()");
int index = secureRandom.nextInt(defaultValues.size());
return defaultValues.get(index);
}
@Test
@BenchmarkOptions(benchmarkRounds = 1, warmupRounds = 0, concurrency = 1)
public void orElse() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElse(getDefaultValue());
System.out.println(result);
assertEquals("Beef", result);
}
Call getDefaultValue()
Beef
DifferenceOptionalOrElseOrElseGetTest.orElse: [measured 1 out of 1 rounds, threads: 1 (sequential)]
round: 0.00 [+- 0.00], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 0, GC.time: 0.00, time.total: 0.01, time.warmup: 0.00, time.bench: 0.00
orElseGet
Difference Between Optional orElse and orElseGet 建立 Optional 容器,取得容器內的值,若值為 Null 則傳回預設值,值如果存在,不會調用 getDefaultValue 方法。
@Test
@BenchmarkOptions(benchmarkRounds = 1, warmupRounds = 0, concurrency = 1)
public void orElseGet() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElseGet(() -> getDefaultValue());
System.out.println(result);
assertEquals("Beef", result);
}
Beef
DifferenceOptionalOrElseOrElseGetTest.orElseGet: [measured 1 out of 1 rounds, threads: 1 (sequential)]
round: 0.03 [+- 0.00], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 0, GC.time: 0.00, time.total: 0.03, time.warmup: 0.00, time.bench: 0.03
orElseBenchmark
Difference Between Optional orElse and orElseGet 建立 Optional 容器,取得容器內的值,若值為 Null 則傳回預設值,值如果存在,一樣會調用 getDefaultValue 方法,比較沒有效率,執行 100 萬次,效能測試。
@Test
public static String defaultValue() {
int index = secureRandom.nextInt(defaultValues.size());
return defaultValues.get(index);
}
@Test
@BenchmarkOptions(benchmarkRounds = 1000000, warmupRounds = 1, concurrency = 1)
public void orElseBenchmark() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElse(defaultValue());
assertEquals("Beef", result);
}
DifferenceOptionalOrElseOrElseGetTest.orElseBenchmark: [measured 1000000 out of 1000001 rounds, threads: 1 (sequential)]
round: 0.00 [+- 0.00], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 1, GC.time: 0.05, time.total: 1.39, time.warmup: 0.00, time.bench: 1.39
orElseGetBenchmark
Difference Between Optional orElse and orElseGet 建立 Optional 容器,取得容器內的值,若值為 Null 則傳回預設值,值如果存在,不會調用 getDefaultValue 方法,執行 100 萬次,效能測試。
@Test
@BenchmarkOptions(benchmarkRounds = 1000000, warmupRounds = 1, concurrency = 1)
public void orElseGetBenchmark() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElseGet(() -> defaultValue());
assertEquals("Beef", result);
}
DifferenceOptionalOrElseOrElseGetTest.orElseGetBenchmark: [measured 1000000 out of 1000001 rounds, threads: 1 (sequential)]
round: 0.00 [+- 0.00], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 1, GC.time: 0.05, time.total: 1.24, time.warmup: 0.03, time.bench: 1.21
測試結果
方法 | 耗時 (秒/100w) |
---|---|
orElseBenchmark | 1.39 |
orElseGetBenchmark | 1.21 |
DifferenceOptionalOrElseOrElseGetTest.java
Difference Between Optional orElseGet and orElse 新增單元測試,驗證是否符合預期。
package org.ruoxue.java_147.optional;
import static org.junit.Assert.*;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
import com.carrotsearch.junitbenchmarks.BenchmarkRule;
public class DifferenceOptionalOrElseOrElseGetTest {
@Rule
public BenchmarkRule benchmarkRule = new BenchmarkRule();
private static SecureRandom secureRandom = null;
public static final String SHA1PRNG = "SHA1PRNG";
public static List<String> defaultValues = Arrays.asList("DEFAULT_Beef", "DEFAULT_Chicken", "DEFAULT_Duck");
static {
new Static();
}
protected static class Static {
public Static() {
try {
secureRandom = SecureRandom.getInstance(SHA1PRNG);
secureRandom.setSeed(System.nanoTime());
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
public static String getDefaultValue() {
System.out.println("Call getDefaultValue()");
int index = secureRandom.nextInt(defaultValues.size());
return defaultValues.get(index);
}
@Test
@BenchmarkOptions(benchmarkRounds = 1, warmupRounds = 0, concurrency = 1)
public void orElse() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElse(getDefaultValue());
System.out.println(result);
assertEquals("Beef", result);
}
@Test
@BenchmarkOptions(benchmarkRounds = 1, warmupRounds = 0, concurrency = 1)
public void orElseGet() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElseGet(() -> getDefaultValue());
System.out.println(result);
assertEquals("Beef", result);
}
public static String defaultValue() {
int index = secureRandom.nextInt(defaultValues.size());
return defaultValues.get(index);
}
@Test
@BenchmarkOptions(benchmarkRounds = 1000000, warmupRounds = 1, concurrency = 1)
public void orElseBenchmark() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElse(defaultValue());
assertEquals("Beef", result);
}
@Test
@BenchmarkOptions(benchmarkRounds = 1000000, warmupRounds = 1, concurrency = 1)
public void orElseGetBenchmark() {
Optional<String> opt = Optional.ofNullable("Beef");
String result = opt.orElseGet(() -> defaultValue());
assertEquals("Beef", result);
}
}
心得分享
Difference Between Optional orElse and orElseGet Methods in Java 使用 junit-benchmarks 執行效能測試,比較兩個方法的執行時間, orElseGet 比 orElse 方法有效率, Difference Between Optional orElseGet and orElse 提供這兩個方法的區別與測試。