概述
- 函数式编程思想的不可变列表,所有成员都是一经创建不可变的。灵感来自于 Scala List
- 用递归算法实现的数据结构,同时也是用来实现递归算法的数据结构,FList具备部分与整体一致的结构设计,同时尾部都有一个nil作为递归跳出点。
- “左折叠”和“右折叠”是非常强大的操作:
- foldLeft : op(a,b,c) = op(op(op(a),b),c)
- foldRight : op(a,b,c) = op(a,op(b,op(c)))
- 大多数列表操作都可以通过折叠操作实现,不可变列表自身的很多方法也是通过折叠操作实现的,如反向、合并、筛选、排序等。
- FList 的很多方法都是接受函数作为参数的 “高阶方法”,比如:
- generate:不可变列表生成器,
- 第一个参数是作为种子的初始列表,
- 第二个是由当前列表推出下一个元素的函数,例如:x -> x.head + 1
- 第三个是新生成元素的个数。
- filter : 过滤,留下符合条件的
- remove:反向过滤,删除符合条件的
- map :列表元素类型转变
- reduce :聚合
- exist:是否存在一个判断
- forall :是否全部符合的判断
- count:按过滤条件计数
- foreach :对列表元素依次执行操作
- isort:插入排序,需传入比较函数
- msort:归并排序,需传入比较函数
- generate:不可变列表生成器,
源码
这是一个无外部依赖可直接运行的代码
package demo; import java.util.ArrayList; import java.util.Comparator; import java.util.StringJoiner; import java.util.function.*; import java.util.stream.Stream; public class Demo { public static void main(String[] args) { ArrayList<Integer> list = FList .generate(FList.of(0), x -> x.head + 1, 10) .map(x -> x * x) .filter(x -> x % 2 == 0) .foldRight(new ArrayList<>(), (x, y) -> { x.add(y); return x; }); System.out.println(list.parallelStream().reduce(0, (x, y) -> x + y)); list = Stream.iterate(0, x -> x + 1).limit(9) .map(x -> x * x) .filter(x -> x % 2 == 0) .collect(ArrayList::new, (x, y) -> x.add(y), ArrayList::addAll); System.out.println(list.parallelStream().reduce(0, (x, y) -> x + y)); } } final class FList<T> { public final T head; public final FList<T> tail; public final int length; public final boolean isEmpty; private FList() { head = null; tail = null; isEmpty = true; length = 0; } private FList(T i, FList<T> n) { head = i; tail = n; isEmpty = false; length = n.length + 1; } public FList<T> add(T item) { return new FList<>(item, this); } public FList<T> reverse() { return foldLeft(nil, (x, y) -> x.add(y)); } public <U> U foldLeft(U i, BiFunction<U, T, U> f) { return isEmpty ? i : tail.foldLeft(f.apply(i, head), f); } public <U> U foldRight(U i, BiFunction<U, T, U> f) { return isEmpty ? i : f.apply(tail.foldRight(i, f), head); } public FList<T> filter(Predicate<T> p) { return foldRight(nil, (x, y) -> p.test(y) ? x.add(y) : x); } public FList<T> remove(Predicate<T> p) { return filter(p.negate()); } public boolean exist(Predicate<T> p) { return !isEmpty && (p.test(head) || tail.exist(p)); } public boolean forAll(Predicate<T> p) { return !exist(p.negate()); } public int count(Predicate<T> p) { return foldLeft(0, (x, y) -> p.test(y) ? x + 1 : x); } public FList<T> merge(FList<T> other) { return other == null || other.isEmpty ? this : other.foldRight(this, (x, y) -> x.add(y)); } @Override public String toString() { return foldRight(new StringJoiner(",", "[", "]"), (x, y) -> x.add(y.toString())).toString(); } public FList<T> sort(Comparator<T> c) { return isEmpty ? nil : ins(c, head, tail.sort(c)); } public FList<T> drop(int n) { return n <= 0 || isEmpty ? this : tail.drop(n - 1); } public void foreach(Consumer<T> a) { if (!isEmpty) { a.accept(head); tail.foreach(a); } } public <R> FList<R> map(Function<T, R> map) { return foldRight(nil, (x, y) -> x.add(map.apply(y))); } public T reduce(T i, BinaryOperator<T> f) { return isEmpty ? i : tail.reduce(f.apply(i, head), f); } public static final FList nil = new FList<>(); public static <T> FList<T> of(T... args) { return a2f(args, args.length - 1); } private static <T> FList<T> a2f(T[] a, int i) { return i < 0 ? nil : new FList<>(a[i], a2f(a, i - 1)); } private static <T> FList<T> ins(Comparator<T> c, T h, FList<T> t) { return t.isEmpty || c.compare(h, t.head) > -1 ? t.add(h) : ins(c, h, t.tail).add(t.head); } public static <T> FList<T> generate(FList<T> r, Function<FList<T>, T> f, int m) { return m == 1 ? r : generate(new FList<>(f.apply(r), r), f, m - 1); } }
用数学归纳法生成数组
- 给出一个递归结束的值. 例如: f(1) =1
- 指定 f = f(n-1).
- 用 f 定义 f(n) . 例如:f(n) = f(n-1) + 1
//奇数数组 ,odd(5) = [1,3,5,7,9] private static FList<Integer> odd(int n) { //定义f(1)的值 if (n == 1) return FList.of(1); //指定 f(n-1)的函数 FList<Integer> f = odd(n - 1); //根据f(n-1)的函数推断f(n)的值 return f.add(f.head + 2); } //单行代码:FList.generate(FList.of(1), x -> x.head + 2, 5) //阶乘数组 fact(10) = [1,2,6,24,120,720,5040,40320,362880,3628800] private static FList<Integer> fact(int n) { if (n <= 1) return FList.of(1); FList<Integer> f = fact(n - 1); return f.add(f.head * (f.length + 1)); } //单行代码:FList.generate(FList.of(1), x -> x.head * (x.length + 1), 10) //菲波拉契亚数组 fib(10) = [1,1,2,3,5,8,13,21,34,55] private static FList<Integer> fib(int n) { if (n <= 2) return FList.of(1, 1); FList<Integer> f = fib(n - 1); return f.add(f.head + f.tail.head); } //单行代码:FList.generate(FList.of(1, 1), x -> x.head + x.tail.head, 9)
/* π = 2 + 2/3 + 2/3*2/5 + 2/3*2/5*3/7 + ... + f(n-1) * n/(2*n+1) 数学归纳法生成数列的应用:计算圆周率的近似值 */ import j.i.FList; public class Main { public static void main(String[] args) { System.out.println(pi(50).reduce(0d, (x, y) -> x + y)); //=> 3.141592653589793 } private static FList<Double> pi(int n) { if (n == 0) return FList.of(2d); FList<Double> f = pi(n - 1); return f.add(f.head * n / (2 * n + 1)); } }
//单行代码 FList.generate(FList.of(2d), x -> x.head * x.length / (x.length * 2 + 1), 51).reduce(0d, (x, y) -> x + y); //=> 3.141592653589793