Java 函数式编程「二」

打印 上一主题 下一主题

主题 580|帖子 580|积分 1740

上回,聊聊函子 functor。
functor 是一个容器。该容器的 value 属性指向被包裹的数据;该容器的 map 方法对容器进行映射变换。

以下代码实现一个最普通的 functor,称之为 Just, 根据 map 的传参 fn 对 value 进行变换:
  1. class Just<T> {
  2.   private final T value;
  3.   private Just(T value) {
  4.     this.value = value;
  5.   }
  6.   public static <T> Just<T> of(T value) {
  7.     return new Just<>(value);
  8.   }
  9.   public <R> Just<R> map(Function<T, R> fn) {
  10.     return of(fn.apply(this.value));
  11.   }
  12.   public T flat() {
  13.     return this.value;
  14.   }
  15. }
复制代码
map 会继续返回 functor,因此可以链式调用:
  1. public static void main(String[] args) {
  2.   System.out.println(
  3.     Just.of(1)
  4.       .map(a -> a + 2)
  5.       .map(a -> a * a)
  6.       .flat()
  7.   );
  8. }
复制代码
将数据用容器 functor 包装,通过唯一的 map 方法对数据进行变换,使得我们很容易封装类似切面的逻辑。例如:将判空的逻辑封装到 map 中,得到函子 Maybe。
  1. class Maybe<T> {
  2.   public static final Maybe<?> EMPTY = new Maybe(null);
  3.   private final T value;
  4.   private Maybe(T value) {
  5.     this.value = value;
  6.   }
  7.   public static <T> Maybe<T> of(T value) {
  8.     if (value == null) {
  9.       return (Maybe<T>) EMPTY;
  10.     } else {
  11.       return new Maybe<>(value);
  12.     }
  13.   }
  14.   public <R> Maybe<R> map(Function<T, R> fn) {
  15.     if (this == EMPTY) {
  16.       return (Maybe<R>) EMPTY;
  17.     } else {
  18.       return of(fn.apply(this.value));
  19.     }
  20.   }
  21.   public T orElse(T v) {
  22.     if (this == EMPTY) {
  23.       return v;
  24.     } else {
  25.       return this.value;
  26.     }
  27.   }
  28. }
复制代码
由于 Maybe 的 map 中包含判空的逻辑,因此调用 map 不用考虑空值,只需要在最后考虑空值。它使得我们更多地关注正常数据流。
  1. class Person {
  2.   public String name;
  3.   public Car car;
  4. }
  5. class Car {
  6.   public String label;
  7. }
  8. public class Test {
  9.   public static void main(String[] args) {
  10.     Person apolis = new Person();
  11.     apolis.name = "apolis";
  12.     System.out.println(
  13.       Maybe.of(apolis)
  14.         .map(p -> p.car)
  15.         .map(c -> c.label)
  16.         .orElse("no car")
  17.     );
  18.   }
  19. }
复制代码
Maybe 函子在 java 中对应的实现是类 Optional。
如果你能找出下面代码里的问题,就证明你已经掌握了 Optional 的用法:
  1. // 问题代码
  2. String name = "";
  3. Optional<String> optional = result.getPrimaryMap()
  4.   .values().stream().findFirst();
  5. if (optional.isPresent()) {
  6.   name = optional.get();
  7. }
复制代码
java 有了 Optional,可以表达更多的信息。例如:一个方法的返回值类型是 Optional,会告诉调用者,该方法有可能返回空值。如果我们能统一规范:会返回空值的方法都改为返回 Optional,将使 api 更易用。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

勿忘初心做自己

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表