一、依赖
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
</dependency>
二、使用示例
package com.cagmss.function;
import com.cagmss.common_core.utils.number.NumberUtils;
import io.vavr.Function1;
import io.vavr.Function2;
import io.vavr.Function3;
import io.vavr.Tuple2;
import io.vavr.control.Option;
import io.vavr.control.Try;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Objects;
@Slf4j
public class FunctionDemo {
public static void main(String[] args) {
// Integer orNull = Option.of(0)
// .map(o -> 1 / o)
// .transform(op->op.get());
// System.out.println(orNull);
// String s = Try.of(() -> 1 / 0)
// .recover(Exception.class, (e) -> null)
// .filter(Objects::nonNull)
// .map(o -> o.toString())
// .get();
//
// System.out.println(s);
tryTest();
}
private static void tryTest() {
// onFailure 当 元素为空 或 发送异常时 执行消费 (onFailure实际类似于peek 瞧一下异常)
// onSuccess 有元素 并且无异常时执行
Try<Integer> onFailure = Try.of(() -> 1 / 1)
// .filter(i -> i > 10)
.onFailure((e) -> log.error("失败{}", e.getMessage()))
.onFailure(NullPointerException.class, (ne) -> System.out.println(ne.getMessage())) // 消费指定异常
.onSuccess(o -> log.info("成功{}", o));
// 关闭流
Try<FileReader> readers = Try.of(() -> new FileReader(""));
readers.mapTry(BufferedReader::new)
.andThenTry((name) -> {
int i = 1 / 0;
while (true) {
String line = name.readLine();
if (Objects.isNull(line)) {
break;
}
System.out.println(line);
}
}).onFailure(e -> log.error(e.getMessage()))
.andFinally(() -> readers.andThenTry(InputStreamReader::close));
// withResources 接收一个AutoCloseable 实现类,of的前一个阶段就会关闭,因此下面的用法是错误的,暂时不知道能干什么用
// 如果想操作io 可以像上面的示例写法
// Try.withResources(() -> new BufferedReader(new FileReader("")))
// .of(BufferedReader::readLine)
// .get();
// failed 获取异常对象,如果未出现异常,则get时会抛出new NoSuchElementException("Success.failed()"))
Try<Throwable> failed = Try.of(() -> 1 / 0)
.peek(i -> log.info(String.valueOf(i)))
.failed();
// getCause 获取异常 无异常时抛出 throw new UnsupportedOperationException("getCause on Success");
Throwable cause = Try.of(() -> 1 / 0)
.getCause();
// andFinally 无论是否发生异常 都会执行
Try<Integer> andFinally = Try.of(() -> 1 / 1)
.peek(i -> log.info(String.valueOf(i)))
.andFinally(() -> log.info("最终执行"))
.andFinallyTry(() -> log.info("执行"));
// andThenTry、andThen,流程中对数据的一次消费,无异常 且 未被过滤 时执行
Try<Integer> integers = Try.of(() -> 1 / 1)
.filter(i -> i > 10)
.peek(i -> log.info(String.valueOf(i)))
.andThenTry((i) -> log.info("andThenTry {}", i))
.andThenTry((i) -> log.info("andThenTry {}", i));
// filter 过滤元素 元素非空时执行
Try<Integer> integerTry = Try.of(() -> 1 / 1)
// .filter(i -> i > 10) // 过滤失败 get() 抛出默认异常 new NoSuchElementException("Predicate does not hold for " + get())
.filter(i -> false, (o) -> new RuntimeException("过滤失败,创建异常")) // 断言为false 抛出指定异常 可接受断言参数
// .filter(i -> i > 10, () -> new RuntimeException("i小于10异常")) // 断言为false 抛出指定异常
.peek(i -> log.info("过滤结果为true")) // 过滤为false 则不执行
.onFailure((e) -> log.error("filter失败{}", e.getMessage())) // 过滤失败执行 消息:Predicate does not hold for 1
.onSuccess(o -> log.info("filter成功{}", o));
// 元素映射,无异常 且 元素非空时执行
Try<Integer> integers1 = Try.of(() -> 1 / 1)
// .filter(i->i>10)
.map(i -> i + 1)
.mapTry(i -> i * 10)
.onFailure((e) -> log.error("map失败{}", e.getMessage()))
.onSuccess(o -> log.info("map成功{}", o));
// fold 折叠, 异常或无值左边,无异常有值右边
Integer fold = Try.of(() -> 1 / 1)
.fold(e -> 10, i -> 10);
// recover 捕获某些异常,然后替换原有值
Integer integers2 = Try.of(() -> 1 / 0)
.peek(NumberUtils::throwInvalidDouble)
// .filter(o -> o > 10)
.recover(IOException.class, e -> {
log.warn("IOException:" + e.getMessage());
return 1;
})
.recover(ArithmeticException.class, e -> {
log.warn("ArithmeticException:" + e.getMessage());
return 1;
})
.onFailure(e -> log.error(e.getMessage()))
.getOrElseThrow(e -> new RuntimeException(e));
// recoverWith 与 recover类似,返回一个新的Try实例
Try<Integer> integers3 = Try.of(() -> 1 / 0)
.recoverWith(Exception.class, e -> Try.of(() -> 0));
// Try类型嵌套扁平化
Try<Integer> integers4 = Try.of(() -> Try.of(() -> 0))
.flatMap(t -> t);
System.out.println(integers4.get());
}
private static void function() {
Function2<Integer, Integer, Integer> f21 = (a, b) -> a - b;
Function2<Integer, Integer, Integer> f22 = (a, b) -> a * b;
// fr(f22(a,b)) 将结果传递给下一个函数,函数只能是一元的,因为返回值只有一个
Function2<Integer, Integer, Integer> then = f21.andThen((r) -> r + 10);
// 将参数包装为tuple
Function1<Tuple2<Integer, Integer>, Integer> tupled = f21.tupled();
科里化 f(a,b,c) => f(a) f(b) f(c)
// 将第一个参数值固定,返回一个降级后的参数
Function1<Integer, Integer> apply1 = f21.curried().apply(1);
// 继续科里化后如果无参了,则将结果返回
Integer apply = apply1.curried().apply(1);
System.out.println("科里化 " + apply);
// 函数参数逆转
Function2<Integer, Integer, Integer> reversed = f21.reversed();
// 部分应用,将参数值固定,返回一个降参的函数,和科里化有些类似,
Function1<Integer, Integer> apply2 = reversed.apply(1);
Integer apply3 = apply2.apply(2);
System.out.println("逆转,部分应用 " + apply3);
// 区别在于科里化将多参函数转换为1个参数的函数
Function3<Integer, Integer, Integer, Integer> f3 = (a, b, c) -> a + b + c;
Function1<Integer, Function1<Integer, Integer>> apply5 = f3.curried().apply(1);
Integer res = apply5.apply(4).apply(3);
System.out.println("3参科里化 " + res);
// 部分应用
Function1<Integer, Integer> apply6 = f3.apply(1, 2);
Integer apply7 = apply6.apply(1);
System.out.println("3参部分应用" + apply7);
// 返回当前函数的参数个数
int arity = f21.arity();
System.out.println("函数参数数量 " + arity);
记忆,参数相同的情况下,反复执行函数 只计算一次,
// 原理:将函数参数封装元组作为 map的key
Function2<Integer, Integer, Integer> memoized = f21.memoized();
Integer apply4 = memoized.apply(1, 2);
System.out.println(apply4);
apply4 = memoized.apply(2, 1);
System.out.println(apply4);
函数静态方法部分:
// 给函数一个常量值,无论传什么参数,结果依然为常量值
Function2<Object, Object, Integer> constant = Function2.constant(2);
System.out.println("函数常量 " + constant.apply(1, 1));
Function1<Object, Integer> apply8 = constant.apply(1);
System.out.println(apply8.apply(2));
// 接收一个 非检查异常 的函数体,将返回值封装为option
// 非get方法会隐藏异常
// get方法会将真实异常隐藏,但会报没有结果异常
Function2<Integer, Integer, Option<Integer>> lift = Function2.lift((a, b) -> a / b);
Option<Integer> option = lift.apply(1, 0);
Integer orNull = option.getOrNull();
System.out.println("getOrNull" + orNull); // null
// System.out.println("option.get() = " + option.get()); // java.util.NoSuchElementException: No value present
// 接收一个 非检查异常 的函数体,将结果封装为try
Function2<Integer, Integer, Try<Integer>> lift2 = Function2.liftTry((a, b) -> a / b);
Try<Integer> apply9 = lift2.apply(1, 0);
// System.out.println("apply9.get() = " + apply9.get()); // java.lang.ArithmeticException: / by zero
Function2<Integer, Integer, Integer> narrow = Function2.narrow((a, b) -> a + b);
Integer apply10 = narrow.apply(1, 2);
System.out.println(apply10);
}
}