java8 函数式编程学习

重点:一句话总结两种的关系:面向对象编程是对数据进行抽象;而函数式编程是对行为进行抽象

@FunctionalInterface注解

1.用此注解注解的接口即为函数式接口,并且接口中只有一个抽象方法,用作Lambda表达式的类型。
2.Lambda表达式->就像是一个匿名函数,将行为像数据那样传递。
3.表达式:函数式接口 实体对象=Lambda表达式。Lambda表达式返回的其实就是一个接口。

java内置的函数接口

1. Predicate<T>

参数类型:T
返回值:boolean
示例:Predicate<String> isAdmin = name -> "admin".equals(name);
2. Consumer<T>

参数:T
返回值:void
示例:Consumer<String> print = msg -> System.out.println(msg);
3. Function<T,R>

参数:T
返回值:R
示例:Function<Long, String> toStr = value -> String.valueOf(value);
4. Supplier<T>

参数:none
返回值:T
示例:Supplier<Date> now = () -> new Date();
5. UnaryOperator<T>

参数:T
返回值:T
示例:UnaryOperator<Boolean> negation = value -> !value.booleanValue();
6. BinaryOperator<T>

参数:(T, T)
返回值:T
示例:BinaryOperator<Integer> intDouble = (i, j) -> i + j;
7. Runnable

参数:none
返回值:void
示例:Runnable helloWord = () -> System.out.println("Hello World");
8. Callable<T>

参数:none
返回值:T
示例:Callable<LocalDate> now1 = ()->LocalDate.now();

方法引用,java8支持新的方法引用方式

静态方法引用:className::methodName
实例方法引用:instanceName::methodName
超类实体方法引用:supper::mehtodName
构造函数方法引用:className::new
数组构造方法引用:ClassName[]::new

类型推断,java8可以根据上下文信息自动推断Lambda表达式中的信息,有可能存在推断失效的情况,比如两个同名方法,如下代码

    // Supplier<String>, Callable<String> 具有相同的方法签名
    private void print(Supplier<String> stringSupplier){
        System.out.println("Hello " + stringSupplier.get());
    }

    private void print(Callable<String> stringCallable){
        try {
            System.out.println("Hello " + stringCallable.call());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    {
        // Error, 因为两个print同时满足需求
        print(()->"World");
        // 使用类型转换,为编译器提供更多信息
        print((Supplier<String>) ()->"World");

        print((Callable<String>) ()-> "world");

三定律

1.类胜于方法。 如果在继承链中有方法体或抽象的方法声明,那么就可以忽略接口中定义的方法。

2.子类胜于父类。 如果一个接口继承另一个接口,且两个接口都定义了一个默认方法,那么子接口中定义的方法胜出。

3.没有规则三。 如果上面两条规则不适用,子类要么实现该方法,要么将该方法声明为抽象方法。

接口中可以有默认实现方法,以及接口中可以有静态方法。

惰性求值VS及早求值

Stream 中存在两类方法,不产生值的方法称为惰性方法;从 Stream 中产生值的方法叫做及早求值方法。

判断一个方法的类别很简单:如果返回值是 Stream,那么就是惰性方法;如果返回值是另一个值或为空,那么就是及早求值方法。


惰性方法返回的 Stream 对象不是一个新的集合,而是创建新集合的配方,Stream 本身不会做任何迭代操作,只有调用及早求值方法时,才会开始真正的迭代。


整个过程与 Builder 模式有共通之处,惰性方法负责对 Stream 进行装配(设置 builder 的属性),调用及早求值方法时(调用 builder 的 build 方法),按照之前的装配信息进行迭代操作。

常见的及早求值方法有:collect,max,min,count,findAny,findFirst,allMatch,anyMatch,noneMatch,forEach,reduce
惰性求值方法有:filter,map,peek,其他(distinct,sorted,limit,skip)

Optional

Java 程序中出现最多的异常就是 NullPointerException,没有之一。Optional 的出现力求改变这一状态。

Optional 对象相当于值的容器,而该值可以通过 get 方法获取,同时 Optional 提供了很多函数用于对值进行操作,从而最大限度的避免 NullPointerException 的出现。

Optional 与 Stream 的用法基本类型,所提供的方法同样分为惰性和及早求值两类,惰性方法主要用于流程组装,及早求值用于最终计算。

猜你喜欢

转载自blog.csdn.net/ysk_xh_521/article/details/81190113