mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
Opt修改
* ofBlankAble入参和泛型改为String * ofEmptyAble额外判断集合内元素全部为null的情况 * peek直接调用ifPresent * peeks改为可爱的写法 - 移除名字太长的ifPresentOrElse - 移除没有必要的orElseThrow(Function,String) + 新增orElseRun,对应一些不满足条件时调用的简单而又无返回值操作
This commit is contained in:
parent
922d460fbe
commit
d6118fe057
@ -26,13 +26,13 @@ package cn.hutool.core.lang;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
import cn.hutool.core.lang.func.VoidFunc0;
|
|
||||||
import cn.hutool.core.text.StrUtil;
|
import cn.hutool.core.text.StrUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
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.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
@ -92,11 +92,10 @@ public class Opt<T> {
|
|||||||
* 返回一个包裹里元素可能为空的{@code Opt},额外判断了空字符串的情况
|
* 返回一个包裹里元素可能为空的{@code Opt},额外判断了空字符串的情况
|
||||||
*
|
*
|
||||||
* @param value 传入需要包裹的元素
|
* @param value 传入需要包裹的元素
|
||||||
* @param <T> 包裹里元素的类型
|
|
||||||
* @return 一个包裹里元素可能为空,或者为空字符串的 {@code Opt}
|
* @return 一个包裹里元素可能为空,或者为空字符串的 {@code Opt}
|
||||||
*/
|
*/
|
||||||
public static <T> Opt<T> ofBlankAble(final T value) {
|
public static Opt<String> ofBlankAble(final String value) {
|
||||||
return StrUtil.isBlankIfStr(value) ? empty() : new Opt<>(value);
|
return StrUtil.isBlank(value) ? empty() : new Opt<>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,7 +108,7 @@ public class Opt<T> {
|
|||||||
* @since 5.7.17
|
* @since 5.7.17
|
||||||
*/
|
*/
|
||||||
public static <T, R extends Collection<T>> Opt<R> ofEmptyAble(final R value) {
|
public static <T, R extends Collection<T>> Opt<R> 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<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果包裹里的值存在,就执行传入的值存在时的操作({@link Consumer#accept})
|
|
||||||
* 否则执行传入的值不存在时的操作({@link VoidFunc0}中的{@link VoidFunc0#call()})
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 例如值存在就打印对应的值,不存在则用{@code Console.error}打印另一句字符串
|
|
||||||
* <pre>{@code
|
|
||||||
* Opt.ofNullable("Hello Hutool!").ifPresentOrElse(Console::log, () -> Console.error("Ops!Something is wrong!"));
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @param action 包裹里的值存在时的操作
|
|
||||||
* @param emptyAction 包裹里的值不存在时的操作
|
|
||||||
* @return this;
|
|
||||||
* @throws NullPointerException 如果包裹里的值存在时,执行的操作为 {@code null}, 或者包裹里的值不存在时的操作为 {@code null},则抛出{@code NPE}
|
|
||||||
*/
|
|
||||||
public Opt<T> ifPresentOrElse(final Consumer<? super T> action, final VoidFunc0 emptyAction) {
|
|
||||||
if (isPresent()) {
|
|
||||||
action.accept(value);
|
|
||||||
} else {
|
|
||||||
emptyAction.callWithRuntimeException();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果包裹里的值存在,就执行传入的值存在时的操作({@link Function#apply(Object)})支持链式调用、转换为其他类型
|
|
||||||
* 否则执行传入的值不存在时的操作({@link VoidFunc0}中的{@link VoidFunc0#call()})
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 如果值存在就转换为大写,否则用{@code Console.error}打印另一句字符串
|
|
||||||
* <pre>{@code
|
|
||||||
* String hutool = Opt.ofBlankAble("hutool").mapOrElse(String::toUpperCase, () -> Console.log("yes")).mapOrElse(String::intern, () -> Console.log("Value is not present~")).get();
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @param <U> map后新的类型
|
|
||||||
* @param mapper 包裹里的值存在时的操作
|
|
||||||
* @param emptyAction 包裹里的值不存在时的操作
|
|
||||||
* @return 新的类型的Opt
|
|
||||||
* @throws NullPointerException 如果包裹里的值存在时,执行的操作为 {@code null}, 或者包裹里的值不存在时的操作为 {@code null},则抛出{@code NPE}
|
|
||||||
*/
|
|
||||||
public <U> Opt<U> mapOrElse(final Function<? super T, ? extends U> mapper, final VoidFunc0 emptyAction) {
|
|
||||||
if (isPresent()) {
|
|
||||||
return ofNullable(mapper.apply(value));
|
|
||||||
} else {
|
|
||||||
emptyAction.callWithRuntimeException();
|
|
||||||
return empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断包裹里的值存在并且与给定的条件是否满足 ({@link Predicate#test}执行结果是否为true)
|
* 判断包裹里的值存在并且与给定的条件是否满足 ({@link Predicate#test}执行结果是否为true)
|
||||||
* 如果满足条件则返回本身
|
* 如果满足条件则返回本身
|
||||||
@ -359,12 +308,7 @@ public class Opt<T> {
|
|||||||
* @author VampireAchao
|
* @author VampireAchao
|
||||||
*/
|
*/
|
||||||
public Opt<T> peek(final Consumer<T> action) throws NullPointerException {
|
public Opt<T> peek(final Consumer<T> action) throws NullPointerException {
|
||||||
Objects.requireNonNull(action);
|
return ifPresent(action);
|
||||||
if (isEmpty()) {
|
|
||||||
return Opt.empty();
|
|
||||||
}
|
|
||||||
action.accept(value);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -382,8 +326,7 @@ public class Opt<T> {
|
|||||||
*/
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public final Opt<T> peeks(final Consumer<T>... actions) throws NullPointerException {
|
public final Opt<T> peeks(final Consumer<T>... actions) throws NullPointerException {
|
||||||
// 第三个参数 (opts, opt) -> null其实并不会执行到该函数式接口所以直接返回了个null
|
return peek(Stream.of(actions).reduce(Consumer::andThen).orElseGet(() -> o -> {}));
|
||||||
return Stream.of(actions).reduce(this, Opt<T>::peek, (opts, opt) -> null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -455,6 +398,22 @@ public class Opt<T> {
|
|||||||
return isPresent() ? value : supplier.get();
|
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}
|
* 如果包裹里的值存在,则返回该值,否则抛出 {@code NoSuchElementException}
|
||||||
*
|
*
|
||||||
@ -462,7 +421,7 @@ public class Opt<T> {
|
|||||||
* @throws NoSuchElementException 如果包裹里的值不存在则抛出该异常
|
* @throws NoSuchElementException 如果包裹里的值不存在则抛出该异常
|
||||||
*/
|
*/
|
||||||
public T orElseThrow() {
|
public T orElseThrow() {
|
||||||
return orElseThrow(NoSuchElementException::new, "No value present");
|
return orElseThrow(() -> new NoSuchElementException("No value present"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -483,30 +442,6 @@ public class Opt<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 如果包裹里的值存在,则返回该值,否则执行传入的操作,获取异常类型的返回值并抛出
|
|
||||||
*
|
|
||||||
* <p>往往是一个包含 自定义消息 构造器的异常 例如
|
|
||||||
* <pre>{@code
|
|
||||||
* Opt.ofNullable(null).orElseThrow(IllegalStateException::new, "Ops!Something is wrong!");
|
|
||||||
* }</pre>
|
|
||||||
*
|
|
||||||
* @param <X> 异常类型
|
|
||||||
* @param exceptionFunction 值不存在时执行的操作,返回值继承 {@link Throwable}
|
|
||||||
* @param message 作为传入操作执行时的参数,一般作为异常自定义提示语
|
|
||||||
* @return 包裹里不能为空的值
|
|
||||||
* @throws X 如果值不存在
|
|
||||||
* @throws NullPointerException 如果值不存在并且 传入的操作为 {@code null}或者操作执行后的返回值为{@code null}
|
|
||||||
* @author VampireAchao
|
|
||||||
*/
|
|
||||||
public <X extends Throwable> T orElseThrow(final Function<String, ? extends X> exceptionFunction, final String message) throws X {
|
|
||||||
if (isPresent()) {
|
|
||||||
return value;
|
|
||||||
} else {
|
|
||||||
throw exceptionFunction.apply(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换为 {@link Optional}对象
|
* 转换为 {@link Optional}对象
|
||||||
*
|
*
|
||||||
|
@ -9,6 +9,9 @@ import org.junit.Assert;
|
|||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -45,19 +48,6 @@ public class OptTest {
|
|||||||
Assert.assertTrue(isEmpty);
|
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
|
@Test
|
||||||
public void peekTest() {
|
public void peekTest() {
|
||||||
final User user = new User();
|
final User user = new User();
|
||||||
@ -127,11 +117,16 @@ public class OptTest {
|
|||||||
Assert.assertNull(assignException);
|
Assert.assertNull(assignException);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test
|
||||||
public void orElseThrowTest3() {
|
public void orElseRunTest() {
|
||||||
// 获取一个不可能为空的值,否则抛出带自定义消息的自定义异常
|
// 判断一个值是否为空,为空执行一段逻辑,否则执行另一段逻辑
|
||||||
final Object exceptionWithMessage = Opt.empty().orElseThrow(IllegalStateException::new, "Ops!Something is wrong!");
|
Map<String, Integer> map = new HashMap<>();
|
||||||
Assert.assertNull(exceptionWithMessage);
|
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
|
@Test
|
||||||
@ -155,14 +150,8 @@ public class OptTest {
|
|||||||
// 现在,一个ofEmptyAble搞定
|
// 现在,一个ofEmptyAble搞定
|
||||||
final List<String> hutool = Opt.ofEmptyAble(Collections.<String>emptyList()).orElseGet(() -> Collections.singletonList("hutool"));
|
final List<String> hutool = Opt.ofEmptyAble(Collections.<String>emptyList()).orElseGet(() -> Collections.singletonList("hutool"));
|
||||||
Assert.assertEquals(past, hutool);
|
Assert.assertEquals(past, hutool);
|
||||||
Assert.assertEquals(hutool, Collections.singletonList("hutool"));
|
Assert.assertEquals(Collections.singletonList("hutool"), hutool);
|
||||||
}
|
Assert.assertTrue(Opt.ofEmptyAble(Arrays.asList(null, null, null)).isEmpty());
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "ConstantConditions"})
|
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "ConstantConditions"})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user