83 - 剖析Google Guava中用的设计模式(三)

2021-10-22  本文已影响0人  舍是境界

现在主流的编程范式主要有三种,面向过程、面向对象和函数式编程。本文,我们讲讲剩下的一种,函数式编程。

函数式编程并非一个很新的东西,早在 50 多年前就已经出现了。近几年,函数式编程越来越被人关注,出现了很多新的函数式编程语言,比如 Clojure、Scala、Erlang 等。一些非函数式编程语言也加入了很多特性、语法、类库来支持函数式编程,比如 Java、Python、Ruby、JavaScript 等。除此之外,Google Guava 也有对函数式编程的增强功能。

函数式编程因其编程的特殊性,仅在科学计算、数据处理、统计分析等领域,才能更好地发挥它的优势,所以,我个人觉得,它并不能完全替代更加通用的面向对象编程范式。但是,作为一种补充,它也有很大存在、发展和学习的意义。

到底什么是函数式编程?

// 有状态函数: 执行结果依赖b的值是多少,即便入参相同,多次执行函数,函数的返回值有可能不同,因为b值有可能不同。
int b;
int increase(int a) {
  return a + b;
}
// 无状态函数:执行结果不依赖任何外部变量值,只要入参相同,不管执行多少次,函数的返回值就相同
int increase(int a, int b) {
  return a + b;
}

Java 对函数式编程的支持

public class FPDemo {
  public static void main(String[] args) {
    Optional<Integer> result = Stream.of("f", "ba", "hello")
            .map(s -> s.length())
            .filter(l -> l <= 3)
            .max((o1, o2) -> o1-o2);
    System.out.println(result.get()); // 输出2
  }
}
  1. 首先,我们来看下 Stream 类。
add(multiply(subtract(3,1),2),5);
subtract(3,1).multiply(2).add(5);
public class FPDemo {
  public static void main(String[] args) {
    Optional<Integer> result = Stream.of("f", "ba", "hello") // of返回Stream<String>对象
            .map(s -> s.length()) // map返回Stream<Integer>对象
            .filter(l -> l <= 3) // filter返回Stream<Integer>对象
            .max((o1, o2) -> o1-o2); // max终止操作:返回Optional<Integer>
    System.out.println(result.get()); // 输出2
  }
}
  1. 其次,我们再来看下 Lambda 表达式。
// Stream中map函数的定义:
public interface Stream<T> extends BaseStream<T, Stream<T>> {
  <R> Stream<R> map(Function<? super T, ? extends R> mapper);
  //...省略其他函数...
}
// Stream中map的使用方法:
Stream.of("fo", "bar", "hello").map(new Function<String, Integer>() {
  @Override
  public Integer apply(String s) {
    return s.length();
  }
});
// 用Lambda表达式简化后的写法:
Stream.of("fo", "bar", "hello").map(s -> s.length());
(a, b) -> { 语句1; 语句2;...; return 输出; } //a,b是输入参数
Optional<Integer> result = Stream.of("f", "ba", "hello")
        .map(s -> s.length())
        .filter(l -> l <= 3)
        .max((o1, o2) -> o1-o2);
        
// 还原为函数接口的实现方式
Optional<Integer> result2 = Stream.of("fo", "bar", "hello")
        .map(new Function<String, Integer>() {
          @Override
          public Integer apply(String s) {
            return s.length();
          }
        })
        .filter(new Predicate<Integer>() {
          @Override
          public boolean test(Integer l) {
            return l <= 3;
          }
        })
        .max(new Comparator<Integer>() {
          @Override
          public int compare(Integer o1, Integer o2) {
            return o1 - o2;
          }
        });
  1. 最后,我们来看下函数接口。
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);  // 只有这一个未实现的方法
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t); // 只有这一个未实现的方法
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

Guava 对函数式编程的增强

Iterables.transform(Iterable, Function);
Iterators.transform(Iterator, Function);
Collections.transfrom(Collection, Function);
Lists.transform(List, Function);
Maps.transformValues(Map, Function);
Multimaps.transformValues(Mltimap, Function);
...
Iterables.filter(Iterable, Predicate);
Iterators.filter(Iterator, Predicate);
Collections2.filter(Collection, Predicate);
...

小结

上一篇 下一篇

猜你喜欢

热点阅读