From f7e21507358185ba51eca68bc67bb2e88770d662 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Wed, 31 Jul 2024 10:21:27 +0800 Subject: [PATCH] =?UTF-8?q?:rocket:=20feat(=E6=96=B0=E5=A2=9E):=20Optional?= =?UTF-8?q?=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/bunny/stream/OptionalTest.java | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 service/src/test/java/cn/bunny/stream/OptionalTest.java diff --git a/service/src/test/java/cn/bunny/stream/OptionalTest.java b/service/src/test/java/cn/bunny/stream/OptionalTest.java new file mode 100644 index 0000000..8c57e07 --- /dev/null +++ b/service/src/test/java/cn/bunny/stream/OptionalTest.java @@ -0,0 +1,252 @@ +package cn.bunny.stream; + +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +public class OptionalTest { + // 提供默认值以确保不会返回 null。 + // 适用于默认情况下的备选值或简单计算结果。 + @Test + void orElseTest() { + // 如果 optionalName 为空,返回 "Unknown" + Optional optionalName = Optional.empty(); + String result = optionalName.orElse("Unknown"); + System.out.println("Name: " + result); // 输出 Name: Unknown + + // 如果 optionalNumber 不为空,返回其值;否则返回默认值 0 + Optional optionalNumber = Optional.of(10); + int number = optionalNumber.orElse(0); + System.out.println("Number: " + number); // 输出 Number: 10 + } + + // 当生成默认值可能会带来额外开销时,可以使用 orElseGet 来提高性能。 + // 允许生成复杂的默认值或者依赖于条件的值。 + @Test + void orElseGetTest() { + // 如果 optionalName 为空,通过 Supplier 生成默认值 + Optional optionalName = Optional.empty(); + String result = optionalName.orElse("Name not provided"); + System.out.println("Name: " + result); // 输出 Name: Name not provided + + // 如果 optionalScore 为空,通过 Supplier 生成默认值 + Optional optionalScore = Optional.ofNullable(null); + double score = optionalScore.orElseGet(() -> Math.random() * 100); + System.out.println("Score: " + score); // 输出 Score: 随机生成的分数值 + } + + // 当 Optional 为空时,抛出异常以确保程序不会继续执行下去。 + // 用于强制要求 Optional 中必须包含值的场景。 + @Test + void orElseThrowTest() { + // 如果 optionalName 为空,抛出 IllegalArgumentException 异常 + Optional optionalName = Optional.empty(); + try { + String result = optionalName.orElseThrow(() -> new IllegalArgumentException("Name not provided")); + System.out.println("Name: " + result); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); // 输出 Name not provided + } + + // 如果 optionalNumber 为空,抛出 NullPointerException 异常 + Optional optionalNumber = Optional.ofNullable(null); + try { + int number = optionalNumber.orElseThrow(NullPointerException::new); + System.out.println("Number: " + number); + } catch (NullPointerException e) { + System.out.println("Caught exception: " + e.getMessage()); // 输出 Caught exception: null + } + } + + // 条件判断和流程控制: 可以根据 Optional 是否包含值来决定程序的执行路径。 + // 避免空指针异常: 在对可能为 null 的值进行操作之前,先使用 isPresent() 来检查是否存在值,以避免空指针异常的发生。 + // 默认值处理: 结合 isPresent() 和 orElse 或 orElseGet 方法,可以根据 Optional 是否包含值来决定返回默认值或进行其他处理。 + @Test + void isPresentTest() { + // 检查 optionalName 是否包含值 + Optional optionalName = Optional.of("Alice"); + if (optionalName.isPresent()) { + System.out.println("Name is present: " + optionalName.get()); // 输出 Name is present: Alice + } else { + System.out.println("Name not found"); + } + + // 使用 isPresent() 来避免空指针异常 + Optional optionalNumber = Optional.empty(); + if (optionalNumber.isPresent()) { + int number = optionalNumber.get(); // 这里不会执行,因为 optionalNumber 为空 + System.out.println("Number: " + number); + } else { + System.out.println("Number not found"); + } + + // 结合 orElseGet 使用 isPresent() 来提供默认值 + String defaultName = "Default"; + Optional optionalName2 = Optional.empty(); + String result = optionalName2.isPresent() ? optionalName2.get() : defaultName; + System.out.println("Name: " + result); // 输出 Name: Default + } + + // 值转换: 将 Optional 中的值进行转换或者计算。 + // 链式调用: 可以与其他方法如 filter、flatMap 一起使用,实现复杂的值处理逻辑。 + @Test + void mapTest() { + Optional optionalName = Optional.of("Alice"); + + // 将字符串转换为大写 + Optional upperCaseName = optionalName.map(name -> name.toUpperCase()); + System.out.println("Upper case name: " + upperCaseName.get()); // 输出 Upper case name: ALICE + + Optional optionalNumber = Optional.of(10); + + // 对数字进行加倍 + Optional doubledNumber = optionalNumber.map(num -> num * 2); + System.out.println("Doubled number: " + doubledNumber.get()); // 输出 Doubled number: 20 + + Optional optionalEmpty = Optional.empty(); + + // 对空 Optional 进行映射 + Optional mappedEmpty = optionalEmpty.map(value -> value.toUpperCase()); + System.out.println("Mapped empty: " + mappedEmpty.isPresent()); // 输出 Mapped empty: false + } + + // 条件过滤: 根据指定的条件过滤掉不符合要求的值。 + // 优化流程: 在确定 Optional 包含有效值之前,可以使用 filter 进行必要的条件检查。 + @Test + void filterTest() { + // 过滤出长度大于3的名字 + Optional optionalName = Optional.of("Bob"); + Optional filteredName = optionalName.filter(name -> name.length() > 3); + System.out.println("Filtered name: " + filteredName.isPresent()); // 输出 Filtered name: false + + // 过滤出大于10的数字 + Optional optionalNumber = Optional.of(15); + Optional filteredNumber = optionalNumber.filter(num -> num > 10); + System.out.println("Filtered number: " + filteredNumber.get()); // 输出 Filtered number: 15 + + // 对空 Optional 进行过滤 + Optional optionalEmpty = Optional.empty(); + Optional filteredEmpty = optionalEmpty.filter(value -> value > 0); + System.out.println("Filtered empty: " + filteredEmpty.isPresent()); // 输出 Filtered empty: false + } + + // 备选方案: 在原始 Optional 为空时提供一个备选的 Optional 对象。 + // 链式调用: 可以与 orElse, orElseGet 等方法结合使用,实现更复杂的值获取逻辑。 + @Test + void orTest() { + // 如果 optionalName 为空,则返回 backupName + Optional optionalName = Optional.empty(); + Optional backupName = Optional.of("Backup Name"); + Optional result = optionalName.or(() -> backupName); + System.out.println("Result: " + result.get()); // 输出 Result: Backup Name + + // 如果 optionalNumber 不为空,则返回 optionalNumber;否则返回 backupNumber + Optional optionalNumber = Optional.of(5); + Optional backupNumber = Optional.empty(); + Optional resultNumber = optionalNumber.or(() -> backupNumber); + System.out.println("Result number: " + resultNumber.get()); // 输出 Result number: 5 + } + + // 获取值: 当确定 Optional 包含值时,直接获取该值。 + // 注意事项: 使用 get 方法时,必须先通过 isPresent 或者其他条件确保 Optional 包含值,避免抛出异常。 + @Test + void getTest() { + Optional optionalName = Optional.of("Alice"); + + // 直接获取 Optional 中的值 + String name = optionalName.get(); + System.out.println("Name: " + name); // 输出 Name: Alice + + Optional optionalEmpty = Optional.empty(); + + // 尝试从空的 Optional 中获取值,会抛出 NoSuchElementException 异常 + // String emptyName = optionalEmpty.get(); + // System.out.println("Empty Name: " + emptyName); // 抛出 NoSuchElementException + } + + // 处理空值情况: 提供一个异常供给型函数,在 Optional 为空时抛出指定异常。 + // 自定义异常信息: 可以通过自定义的异常类型和消息来更好地描述空值情况。 + @Test + void orElseThrowTest2() { + Optional optionalName = Optional.empty(); + + // 如果 optionalName 为空,则抛出自定义的异常 + String name = optionalName.orElseThrow(() -> new IllegalStateException("Name is not present")); + // 输出异常信息:Exception in thread "main" java.lang.IllegalStateException: Name is not present + } + + // 判断空值: 更直观地判断 Optional 是否为空。 + // 条件逻辑: 可以与其他方法结合使用,优化条件判断逻辑。 + @Test + void isEmptyTest() { + Optional optionalName = Optional.of("Bob"); + Optional optionalEmpty = Optional.empty(); + + // 检查 optionalName 是否为空 + boolean namePresent = !optionalName.isEmpty(); + System.out.println("Name present: " + namePresent); // 输出 Name present: true + + // 检查 optionalEmpty 是否为空 + boolean emptyPresent = !optionalEmpty.isEmpty(); + System.out.println("Empty present: " + emptyPresent); // 输出 Empty present: false + } + + // 非空值的创建: 当确定值不为 null 时,可以使用 of 创建对应的 Optional 对象。 + // 避免空指针异常: 在确定值不为 null 的情况下,使用 of 可以直接创建 Optional 对象,避免后续空指针异常。 + @Test + void ofTest() { + String name = "Alice"; + + // 创建包含非 null 值的 Optional 对象 + Optional optionalName = Optional.of(name); + System.out.println("Name: " + optionalName.get()); // 输出 Name: Alice + + String nullName = null; + + // 尝试使用 null 创建 Optional 对象,会抛出 NullPointerException + // Optional optionalNull = Optional.of(nullName); + // System.out.println("Null Name: " + optionalNull.get()); // 抛出 NullPointerException + } + + // 可能为空的值的创建: 当值可能为 null 时,可以使用 ofNullable 创建对应的 Optional 对象。 + // 安全地处理可能为 null 的情况: 可以避免直接操作可能为 null 的值,提高代码的健壮性。 + @Test + void ofNullableTest() { + String name = "Bob"; + String nullName = null; + + // 创建包含非 null 值的 Optional 对象 + Optional optionalName = Optional.ofNullable(name); + System.out.println("Name: " + optionalName.orElse("Default Name")); // 输出 Name: Bob + + // 创建可能为空的 Optional 对象 + Optional optionalNull = Optional.ofNullable(nullName); + System.out.println("Null Name: " + optionalNull.orElse("Default Name")); // 输出 Null Name: Default Name + } + + // 表示缺失值: 可以用于明确指示某个值不存在的情况。 + // 结合其他方法使用: 可以与 orElse, orElseGet, orElseThrow 等方法结合使用,提供默认值或者处理逻辑。 + @Test + void emptyTest() { + Optional emptyOptional = Optional.empty(); + + // 使用 empty 创建的 Optional 对象没有值 + System.out.println("Empty Optional: " + emptyOptional.isPresent()); // 输出 Empty Optional: false + } + + // 扁平化映射: 用于处理嵌套的 Optional 结构,将嵌套的 Optional 展开为单层结构。 + // 链式调用: 可以与 map 结合使用,进行复杂的值转换和处理。 + @Test + void flatMapTest() { + Optional optionalName = Optional.of("Alice"); + Optional optionalEmpty = Optional.empty(); + + // 使用 flatMap 将 Optional 转换为 Optional + Optional nameLengthOptional = optionalName.flatMap(name -> Optional.of(name.length())); + System.out.println("Name length: " + nameLengthOptional.get()); // 输出 Name length: 5 + + // 如果 Optional 是空的,则 flatMap 不执行映射 + Optional emptyLengthOptional = optionalEmpty.flatMap(value -> Optional.of(value.length())); + System.out.println("Empty length: " + emptyLengthOptional.isPresent()); // 输出 Empty length: false + } +}