Difference Between Optional orElse and orElseGet in Java - Java 147

Difference Between Optional orElse and orElseGet in Java – Java 147

Difference 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)
orElseBenchmark1.39
orElseGetBenchmark1.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 提供這兩個方法的區別與測試。

發佈留言