Java 函数式

interface Strategy {
    String approach(String msg);
}

class Soft implements Strategy {
    @Override
    public String approach(String msg) {
        return msg.toLowerCase() + "?";
    }
}

class Unrelated {
    static String twice(String msg) {
        return msg + " " + msg;
    }
}

public class Strategize {
    Strategy strategy;
    String msg;

    Strategize(String msg) {
        strategy = new Soft(); // [1]
        this.msg = msg;
    }

    void communicate() {
        System.out.println(strategy.approach(msg));
    }

    void changeStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
}

public class Main {
    public static void main(String[] args) {
        Strategy[] strategies = {
                new Strategy() { // [2]
                    @Override
                    public String approach(String msg) {
                        return msg.toLowerCase() + "!";
                    }
                },
                msg -> msg.substring(0, 5), // [3]
                Unrelated::twice // [4]
        };
        Strategize s= new Strategize("Hello there");
        s.communicate();
        for (Strategy newStrategy: strategies) {
            s.changeStrategy(newStrategy);

            s.communicate();
        }
    }
}

/* Output
hello there?
hello there!
Hello
Hello there Hello there
*/
  • [1] Soft 实现了 approach
  • [2] 通过生成匿名内部类实现
  • [3] 通过 Java 8 的 lambda 表达式实现,和匿名内部类有相同的效果,但是写的代码少很多
  • [4] Java 8 的方法引用,:: 左边的是类名,:: 右边的是方法名,不带参数列表

Lambda 表达式

interface Description {
    String brief();
}

interface Body {
    String detailed(String head);
}

interface Multi {
    String twoArg(String head, Double d);
}



public class LambdaExpressions {
    static Body bod = h -> h + " No Parens!"; // [1]

    static Body bod2 = (h) -> h + "More details"; // [2]

    static Description desc = () -> "Short info"; // [3]

    static  Multi mult = (h, n) -> h + n; // [4]

    static Description moreLines = () -> { // [5]
        System.out.println("moreLines()");
        return "from moreLines()";
    };

    public static void main(String[] args) {
        System.out.println(bod.detailed("Oh!"));
        System.out.println(bod2.detailed("Hi!"));
        System.out.println(desc.brief());
        System.out.println(mult.twoArg("Pi!", 3.14159));
        System.out.println(moreLines.brief());
    }
}

/*
Oh! No Parens!
Hi!More details
Short info
Pi!3.14159
moreLines()
from moreLines()
*/
  • [1] 单个参数,没有括号
  • [2] 参数带括号
  • [3] 没有参数,必须使用括号
  • [4] 多个参数必须是用括号
  • [5] 多行代码,要用 {},如果有返回值,要用 return

递归

interface IntCall {
    int call(int arg);
}

public class RecursiveFactorial {
    static IntCall fact;
    public static void main(String[] args) {
        fact = n -> n == 0 ? 1 : n * fact.call(n - 1);

        for (int i = 0; i <= 10; i++) {
            System.out.println(fact.call(i));
        }
    }
}

/*
1
1
2
6
24
120
720
5040
40320
362880
3628800
*/

方法引用

interface Callable { // [1]
    void call(String s);
}

class Describe {
    void show(String msg) { // [2]
        System.out.println(msg);
    }
}

public class MethodReferences {
    static void hello(String name) { // [3]
        System.out.println("Hello" + name);
    }

    static class Description {
        String about;
        Description(String desc) {
            about = desc;
        }

        void help(String msg) { // [4]
            System.out.println(about + " " + msg);
        }
    }

    static class Helper {
        static void assist(String msg) { // [5]
            System.out.println(msg);
        }
    }

    public static void main(String[] args) {
        Describe d = new Describe();
        Callable c = d::show; // [6]
        c.call("call()"); // [7]

        c = MethodReferences::hello; // [8]
        c.call("Bob");

        c = new Description("valuable")::help; // [9]
        c.call("information");

        c = Helper::assist; // [10]
        c.call("Help!");
    }
}

/*
call()
HelloBob
valuable information
Help!
*/
  • [1] 定义一个接口
  • [2] 参数和返回值都符合 Callable 的 call() 方法
  • [3] hello() 遵循 Callable 的 call 方法
  • [4] help 不是 static 方法
  • [5] assist() 是 static 方法
  • [6] d::show 赋值给 c
  • [7] 通过 c 调用 show 方法
  • [8] static 方法引用
  • [9] 实例方法引用
  • [10] static 方法引用

Runnable

class Go {
    static void go() {
        System.out.println("Go::go()");
    }
}

public class RunnableMethodReference {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Anonumous");
            }
        }).start();

        new Thread(
                () -> System.out.println("lambda")
        ).start();

        new Thread(Go::go).start();
    }
}

/*
Anonumous
lambda
Go::go()
*/

Unbound Method References

class X  {
    String f() { return "X::f()"; }
}

interface MakeString {
    String make();
}

interface TransfromX {
    String transform(X x);
}


public class UnboundMethodReference {
    public static void main(String[] args) {
        // MakeString ms = X::f; // [1]
        TransfromX sp = X::f;
        X x = new X();
        System.out.println(sp.transform(x)); // [2]
        System.out.println(x.f()); 
    }
}

/*
X::f()
X::f()
*/
  • [1] 这里看起来方法的签名是一致的,其实不然,X::f 的签名是 X -> String, 因为实例方法还有一个 this 参数
  • [2] 和 TransfromX 签名一致

Constructor Method References

函数的组合,可以通过 compose 来进行函数的组合,例如

import java.util.function.*;

public class FunctionComposition {
    static Function<String, String>
            f1 = s -> {
        System.out.println(s);
        return s.replace('A', '_');
    },
            f2 = s -> s.substring(3),
            f3 = s -> s.toLowerCase(),
            f4 = f1.compose(f2).andThen(f3);

    public static void main(String[] args) {
        System.out.println(f4.apply("ABCxyzASDASDASDAS"));
    }
}

/*
xyzASDASDASDAS
xyz_sd_sd_sd_s
*/

自定义异常

class SimpleExpection extends Exception {}

public class InheritingExceptions {
    public void f() throws SimpleExpection {
        System.out.println("f");
        throw new SimpleExpection();
    }

    public static void main(String[] args) {
        InheritingExceptions exc = new InheritingExceptions();

        try {
            exc.f();
        } catch (SimpleExpection e) {
            System.out.println("catch");
        }

    }
}

/* 输出
f()
Caught
*/
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容