mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
!459 - 拓展ofEmptyAble函数,简化了判空元素list的操作 - ifPresentOrElse现在支持链式调用 - 拓展mapOrElse函数,可用于一些连续的参数校验 - 拓展exec函数,能对NPE和数组越界异常进行友好返回
Merge pull request !459 from 阿超/v5-dev
This commit is contained in:
commit
e7370ef77c
@ -24,9 +24,11 @@
|
||||
*/
|
||||
package cn.hutool.core.lang;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.func.VoidFunc0;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@ -97,6 +99,17 @@ public class Opt<T> {
|
||||
return StrUtil.isBlankIfStr(value) ? empty() : new Opt<>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个包裹里{@code List}集合可能为空的{@code Opt},额外判断了集合内元素为空的情况
|
||||
*
|
||||
* @param value 传入需要包裹的元素
|
||||
* @param <T> 包裹里元素的类型
|
||||
* @return 一个包裹里元素可能为空的 {@code Opt}
|
||||
*/
|
||||
public static <T> Opt<List<T>> ofEmptyAble(List<T> value) {
|
||||
return CollectionUtil.isEmpty(value) ? empty() : new Opt<>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 包裹里实际的元素
|
||||
*/
|
||||
@ -176,11 +189,37 @@ public class Opt<T> {
|
||||
* @param emptyAction 包裹里的值不存在时的操作
|
||||
* @throws NullPointerException 如果包裹里的值存在时,执行的操作为 {@code null}, 或者包裹里的值不存在时的操作为 {@code null},则抛出{@code NPE}
|
||||
*/
|
||||
public void ifPresentOrElse(Consumer<? super T> action, VoidFunc0 emptyAction) {
|
||||
if (value != null) {
|
||||
public Opt<T> ifPresentOrElse(Consumer<? super T> action, VoidFunc0 emptyAction) {
|
||||
if (isPresent()) {
|
||||
action.accept(value);
|
||||
return ofNullable(value);
|
||||
} else {
|
||||
emptyAction.callWithRuntimeException();
|
||||
return empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 如果包裹里的值存在,就执行传入的值存在时的操作({@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 mapper 包裹里的值存在时的操作
|
||||
* @param emptyAction 包裹里的值不存在时的操作
|
||||
* @throws NullPointerException 如果包裹里的值存在时,执行的操作为 {@code null}, 或者包裹里的值不存在时的操作为 {@code null},则抛出{@code NPE}
|
||||
*/
|
||||
public <U> Opt<U> mapOrElse(Function<? super T, ? extends U> mapper, VoidFunc0 emptyAction) {
|
||||
if (isPresent()) {
|
||||
return ofNullable(mapper.apply(value));
|
||||
} else {
|
||||
emptyAction.callWithRuntimeException();
|
||||
return empty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,6 +466,22 @@ public class Opt<T> {
|
||||
return Optional.ofNullable(this.value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 执行一系列操作,如果途中发生 {@code NPE} 和 {@code IndexOutOfBoundsException},返回一个空的{@code Opt}
|
||||
*
|
||||
* @param supplier 操作
|
||||
* @param <T> 类型
|
||||
* @return 操作执行后的值
|
||||
*/
|
||||
public static <T> Opt<T> exec(Supplier<T> supplier) {
|
||||
try {
|
||||
return Opt.ofNullable(supplier.get());
|
||||
} catch (NullPointerException | IndexOutOfBoundsException e) {
|
||||
return empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入参数是否与 {@code Opt}相等
|
||||
* 在以下情况下返回true
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.hutool.core.lang;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@ -9,6 +10,7 @@ import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.stream.Stream;
|
||||
@ -46,11 +48,14 @@ public class OptTest {
|
||||
@Test
|
||||
@Ignore
|
||||
public void ifPresentOrElseTest() {
|
||||
// 这是jdk9中的新函数,直接照搬了过来
|
||||
// 存在就打印对应的值,不存在则用{@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
|
||||
@ -142,6 +147,47 @@ public class OptTest {
|
||||
Assert.assertNull(user.getNickname());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ofEmptyAbleTest() {
|
||||
// 以前,输入一个CollectionUtil感觉要命,类似前缀的类一大堆,代码补全形同虚设(在项目中起码要输入完CollectionU才能在第一个调出这个函数)
|
||||
// 关键它还很常用,判空和判空集合真的太常用了...
|
||||
List<String> past = Opt.ofNullable(Collections.<String>emptyList()).filter(CollectionUtil::isNotEmpty).orElseGet(() -> Collections.singletonList("hutool"));
|
||||
// 现在,一个ofEmptyAble搞定
|
||||
List<String> hutool = Opt.ofEmptyAble(Collections.<String>emptyList()).orElseGet(() -> Collections.singletonList("hutool"));
|
||||
Assert.assertEquals(past, hutool);
|
||||
Assert.assertEquals(hutool, Collections.singletonList("hutool"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapOrElseTest() {
|
||||
// 如果值存在就转换为大写,否则打印一句字符串,支持链式调用、转换为其他类型
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void execTest() {
|
||||
// 有一些资深的程序员跟我说你这个lambda,双冒号语法糖看不懂...
|
||||
// 为了尊重资深程序员的意见,并且提升代码可读性,封装了一下 "try catch NPE 和 数组越界"的情况
|
||||
|
||||
// 以前这种写法,简洁但可读性稍低,对资深程序员不太友好
|
||||
List<String> last = null;
|
||||
String npeSituation = Opt.ofEmptyAble(last).flattedMap(l -> l.stream().findFirst()).orElse("hutool");
|
||||
String indexOutSituation = Opt.ofEmptyAble(last).map(l -> l.get(0)).orElse("hutool");
|
||||
|
||||
// 现在代码整洁度降低,但可读性up,如果再人说看不懂这代码...
|
||||
String npe = Opt.exec(() -> last.get(0)).orElse("hutool");
|
||||
String indexOut = Opt.exec(() -> {
|
||||
List<String> list = new ArrayList<>();
|
||||
// 你可以在里面写一长串调用链 list.get(0).getUser().getId()
|
||||
return list.get(0);
|
||||
}).orElse("hutool");
|
||||
Assert.assertEquals(npe, npeSituation);
|
||||
Assert.assertEquals(indexOut, indexOutSituation);
|
||||
Assert.assertEquals("hutool", npe);
|
||||
Assert.assertEquals("hutool", indexOut);
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
|
Loading…
x
Reference in New Issue
Block a user