接上回,聊聊函子 functor

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

Java 函数式编程「二」

以下代码实现一个最普通的 functor,称之为 Just, 根据 map 的传参 fnvalue 进行变换:

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;
    }
  }
}

由于 Maybemap 中包含判空的逻辑,因此调用 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 更易用。

发表回复