From d6118fe0573443d121f4442bf8d0e86de73e2855 Mon Sep 17 00:00:00 2001 From: VampireAchao Date: Wed, 22 Jun 2022 12:29:29 +0800 Subject: [PATCH] =?UTF-8?q?Opt=E4=BF=AE=E6=94=B9=20*=20ofBlankAble?= =?UTF-8?q?=E5=85=A5=E5=8F=82=E5=92=8C=E6=B3=9B=E5=9E=8B=E6=94=B9=E4=B8=BA?= =?UTF-8?q?String=20*=20ofEmptyAble=E9=A2=9D=E5=A4=96=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E9=9B=86=E5=90=88=E5=86=85=E5=85=83=E7=B4=A0=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E4=B8=BAnull=E7=9A=84=E6=83=85=E5=86=B5=20*=20peek=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E8=B0=83=E7=94=A8ifPresent=20*=20peeks=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E5=8F=AF=E7=88=B1=E7=9A=84=E5=86=99=E6=B3=95=20-=20?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=90=8D=E5=AD=97=E5=A4=AA=E9=95=BF=E7=9A=84?= =?UTF-8?q?ifPresentOrElse=20-=20=E7=A7=BB=E9=99=A4=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E5=BF=85=E8=A6=81=E7=9A=84orElseThrow(Function,String)=20+=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9EorElseRun=EF=BC=8C=E5=AF=B9=E5=BA=94=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E4=B8=8D=E6=BB=A1=E8=B6=B3=E6=9D=A1=E4=BB=B6=E6=97=B6?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E7=9A=84=E7=AE=80=E5=8D=95=E8=80=8C=E5=8F=88?= =?UTF-8?q?=E6=97=A0=E8=BF=94=E5=9B=9E=E5=80=BC=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/core/lang/Opt.java | 115 ++++-------------- .../java/cn/hutool/core/lang/OptTest.java | 41 +++---- 2 files changed, 40 insertions(+), 116 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java index d86c3e03b..4af46995f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Opt.java @@ -26,13 +26,13 @@ package cn.hutool.core.lang; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.func.Func0; -import cn.hutool.core.lang.func.VoidFunc0; import cn.hutool.core.text.StrUtil; -import java.util.Collection; -import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; +import java.util.Collection; +import java.util.Collections; +import java.util.NoSuchElementException; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -92,11 +92,10 @@ public class Opt { * 返回一个包裹里元素可能为空的{@code Opt},额外判断了空字符串的情况 * * @param value 传入需要包裹的元素 - * @param 包裹里元素的类型 * @return 一个包裹里元素可能为空,或者为空字符串的 {@code Opt} */ - public static Opt ofBlankAble(final T value) { - return StrUtil.isBlankIfStr(value) ? empty() : new Opt<>(value); + public static Opt ofBlankAble(final String value) { + return StrUtil.isBlank(value) ? empty() : new Opt<>(value); } /** @@ -109,7 +108,7 @@ public class Opt { * @since 5.7.17 */ public static > Opt ofEmptyAble(final R value) { - return CollUtil.isEmpty(value) ? empty() : new Opt<>(value); + return CollUtil.isEmpty(value) || Collections.frequency(value, null) == value.size() ? empty() : new Opt<>(value); } /** @@ -217,56 +216,6 @@ public class Opt { return this; } - /** - * 如果包裹里的值存在,就执行传入的值存在时的操作({@link Consumer#accept}) - * 否则执行传入的值不存在时的操作({@link VoidFunc0}中的{@link VoidFunc0#call()}) - * - *

- * 例如值存在就打印对应的值,不存在则用{@code Console.error}打印另一句字符串 - *

{@code
-	 * Opt.ofNullable("Hello Hutool!").ifPresentOrElse(Console::log, () -> Console.error("Ops!Something is wrong!"));
-	 * }
- * - * @param action 包裹里的值存在时的操作 - * @param emptyAction 包裹里的值不存在时的操作 - * @return this; - * @throws NullPointerException 如果包裹里的值存在时,执行的操作为 {@code null}, 或者包裹里的值不存在时的操作为 {@code null},则抛出{@code NPE} - */ - public Opt ifPresentOrElse(final Consumer action, final VoidFunc0 emptyAction) { - if (isPresent()) { - action.accept(value); - } else { - emptyAction.callWithRuntimeException(); - } - return this; - } - - - /** - * 如果包裹里的值存在,就执行传入的值存在时的操作({@link Function#apply(Object)})支持链式调用、转换为其他类型 - * 否则执行传入的值不存在时的操作({@link VoidFunc0}中的{@link VoidFunc0#call()}) - * - *

- * 如果值存在就转换为大写,否则用{@code Console.error}打印另一句字符串 - *

{@code
-	 * String hutool = Opt.ofBlankAble("hutool").mapOrElse(String::toUpperCase, () -> Console.log("yes")).mapOrElse(String::intern, () -> Console.log("Value is not present~")).get();
-	 * }
- * - * @param map后新的类型 - * @param mapper 包裹里的值存在时的操作 - * @param emptyAction 包裹里的值不存在时的操作 - * @return 新的类型的Opt - * @throws NullPointerException 如果包裹里的值存在时,执行的操作为 {@code null}, 或者包裹里的值不存在时的操作为 {@code null},则抛出{@code NPE} - */ - public Opt mapOrElse(final Function mapper, final VoidFunc0 emptyAction) { - if (isPresent()) { - return ofNullable(mapper.apply(value)); - } else { - emptyAction.callWithRuntimeException(); - return empty(); - } - } - /** * 判断包裹里的值存在并且与给定的条件是否满足 ({@link Predicate#test}执行结果是否为true) * 如果满足条件则返回本身 @@ -359,12 +308,7 @@ public class Opt { * @author VampireAchao */ public Opt peek(final Consumer action) throws NullPointerException { - Objects.requireNonNull(action); - if (isEmpty()) { - return Opt.empty(); - } - action.accept(value); - return this; + return ifPresent(action); } @@ -382,8 +326,7 @@ public class Opt { */ @SafeVarargs public final Opt peeks(final Consumer... actions) throws NullPointerException { - // 第三个参数 (opts, opt) -> null其实并不会执行到该函数式接口所以直接返回了个null - return Stream.of(actions).reduce(this, Opt::peek, (opts, opt) -> null); + return peek(Stream.of(actions).reduce(Consumer::andThen).orElseGet(() -> o -> {})); } /** @@ -455,6 +398,22 @@ public class Opt { return isPresent() ? value : supplier.get(); } + /** + * 如果包裹里元素的值存在,则返回该值,否则执行传入的操作 + * + * @param action 值不存在时执行的操作 + * @return 如果包裹里元素的值存在,则返回该值,否则执行传入的操作 + * @throws NullPointerException 如果值不存在,并且传入的操作为 {@code null} + */ + public T orElseRun(Runnable action) { + if (isPresent()) { + return value; + } else { + action.run(); + return null; + } + } + /** * 如果包裹里的值存在,则返回该值,否则抛出 {@code NoSuchElementException} * @@ -462,7 +421,7 @@ public class Opt { * @throws NoSuchElementException 如果包裹里的值不存在则抛出该异常 */ public T orElseThrow() { - return orElseThrow(NoSuchElementException::new, "No value present"); + return orElseThrow(() -> new NoSuchElementException("No value present")); } /** @@ -483,30 +442,6 @@ public class Opt { } } - /** - * 如果包裹里的值存在,则返回该值,否则执行传入的操作,获取异常类型的返回值并抛出 - * - *

往往是一个包含 自定义消息 构造器的异常 例如 - *

{@code
-	 * 		Opt.ofNullable(null).orElseThrow(IllegalStateException::new, "Ops!Something is wrong!");
-	 * }
- * - * @param 异常类型 - * @param exceptionFunction 值不存在时执行的操作,返回值继承 {@link Throwable} - * @param message 作为传入操作执行时的参数,一般作为异常自定义提示语 - * @return 包裹里不能为空的值 - * @throws X 如果值不存在 - * @throws NullPointerException 如果值不存在并且 传入的操作为 {@code null}或者操作执行后的返回值为{@code null} - * @author VampireAchao - */ - public T orElseThrow(final Function exceptionFunction, final String message) throws X { - if (isPresent()) { - return value; - } else { - throw exceptionFunction.apply(message); - } - } - /** * 转换为 {@link Optional}对象 * diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java index bcceae3dc..a80dd8636 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java @@ -9,6 +9,9 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; +import java.util.Map; +import java.util.HashMap; +import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -45,19 +48,6 @@ public class OptTest { Assert.assertTrue(isEmpty); } - @Test - @Ignore - public void ifPresentOrElseTest() { - // 存在就打印对应的值,不存在则用{@code System.err.println}打印另一句字符串 - Opt.ofNullable("Hello Hutool!").ifPresentOrElse(Console::log, () -> Console.error("Ops!Something is wrong!")); - - Opt.empty().ifPresentOrElse(Console::log, () -> Console.error("Ops!Something is wrong!")); - - // 拓展为支持链式调用 - Opt.empty().ifPresentOrElse(Console::log, () -> Console.error("Ops!Something is wrong!")) - .ifPresentOrElse(Console::log, () -> Console.error("Ops!Something is wrong!")); - } - @Test public void peekTest() { final User user = new User(); @@ -127,11 +117,16 @@ public class OptTest { Assert.assertNull(assignException); } - @Test(expected = IllegalStateException.class) - public void orElseThrowTest3() { - // 获取一个不可能为空的值,否则抛出带自定义消息的自定义异常 - final Object exceptionWithMessage = Opt.empty().orElseThrow(IllegalStateException::new, "Ops!Something is wrong!"); - Assert.assertNull(exceptionWithMessage); + @Test + public void orElseRunTest() { + // 判断一个值是否为空,为空执行一段逻辑,否则执行另一段逻辑 + Map map = new HashMap<>(); + final String key = "key"; + map.put(key, 1); + Opt.ofNullable(map.get(key)) + .ifPresent(v -> map.put(key, v + 1)) + .orElseRun(() -> map.remove(key)); + Assert.assertEquals((Object) 2, map.get(key)); } @Test @@ -155,14 +150,8 @@ public class OptTest { // 现在,一个ofEmptyAble搞定 final List hutool = Opt.ofEmptyAble(Collections.emptyList()).orElseGet(() -> Collections.singletonList("hutool")); Assert.assertEquals(past, hutool); - Assert.assertEquals(hutool, Collections.singletonList("hutool")); - } - - @Test - public void mapOrElseTest() { - // 如果值存在就转换为大写,否则打印一句字符串,支持链式调用、转换为其他类型 - final String hutool = Opt.ofBlankAble("hutool").mapOrElse(String::toUpperCase, () -> Console.log("yes")).mapOrElse(String::intern, () -> Console.log("Value is not present~")).get(); - Assert.assertEquals("HUTOOL", hutool); + Assert.assertEquals(Collections.singletonList("hutool"), hutool); + Assert.assertTrue(Opt.ofEmptyAble(Arrays.asList(null, null, null)).isEmpty()); } @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "ConstantConditions"})