Java 函数式编程「二」
2023-03-31 10:42:21 时间
接上回,聊聊函子 functor
。
functor
是一个容器。该容器的 value
属性指向被包裹的数据;该容器的 map
方法对容器进行映射变换。
以下代码实现一个最普通的 functor
,称之为 Just
, 根据 map
的传参 fn
对 value
进行变换:
class Just<T> {
private final T value;
private Just(T value) {
this.value = value;
}
public static <T> Just<T> of(T value) {
return new Just<>(value);
}
public <R> Just<R> map(Function<T, R> fn) {
return of(fn.apply(this.value));
}
public T flat() {
return this.value;
}
}
map
会继续返回 functor
,因此可以链式调用:
public static void main(String[] args) {
System.out.println(
Just.of(1)
.map(a -> a + 2)
.map(a -> a * a)
.flat()
);
}
将数据用容器 functor
包装,通过唯一的 map
方法对数据进行变换,使得我们很容易封装类似切面的逻辑。例如:将判空的逻辑封装到 map
中,得到函子 Maybe
。
class Maybe<T> {
public static final Maybe<?> EMPTY = new Maybe(null);
private final T value;
private Maybe(T value) {
this.value = value;
}
public static <T> Maybe<T> of(T value) {
if (value == null) {
return (Maybe<T>) EMPTY;
} else {
return new Maybe<>(value);
}
}
public <R> Maybe<R> map(Function<T, R> fn) {
if (this == EMPTY) {
return (Maybe<R>) EMPTY;
} else {
return of(fn.apply(this.value));
}
}
public T orElse(T v) {
if (this == EMPTY) {
return v;
} else {
return this.value;
}
}
}
由于 Maybe
的 map
中包含判空的逻辑,因此调用 map
不用考虑空值,只需要在最后考虑空值。它使得我们更多地关注正常数据流。
class Person {
public String name;
public Car car;
}
class Car {
public String label;
}
public class Test {
public static void main(String[] args) {
Person apolis = new Person();
apolis.name = "apolis";
System.out.println(
Maybe.of(apolis)
.map(p -> p.car)
.map(c -> c.label)
.orElse("no car")
);
}
}
Maybe
函子在 java 中对应的实现是类 Optional
。
如果你能找出下面代码里的问题,就证明你已经掌握了 Optional
的用法:
// 问题代码
String name = "";
Optional<String> optional = result.getPrimaryMap()
.values().stream().findFirst();
if (optional.isPresent()) {
name = optional.get();
}
java 有了 Optional
,可以表达更多的信息。例如:一个方法的返回值类型是 Optional<XXX>
,会告诉调用者,该方法有可能返回空值。如果我们能统一规范:会返回空值的方法都改为返回 Optional
,将使 api 更易用。
相关文章
- 深入探讨Java中的异常与错误处理
- 研究学习Kotlin的一些方法
- 数据显示Java热度持续下落,日子屈指可数?
- 2017年5月编程语言排行榜:Java与C语言优势正开始缩小
- Java多线程之内置锁与显示锁
- Java线程池的理论与实践
- 白话阿里巴巴Java开发手册(编程规约)
- 关于Java你不知道的十件事
- Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令
- Java实现高斯模糊和图像的空间卷积
- Java阻塞队列实现原理分析
- NPM使用技巧
- Node.js对Java开发者而言是什么?
- Java反射机制应用实践
- 理解RxJava中的Single和Completable
- 2017年你不能错过的Java类库
- 大规模集群下的Hadoop NameNode
- 从源码解密Spark内存管理
- 2017年3月编程语言排行榜:Swift首次进入前十
- JVM热点技术:Java类的加载机制