Java8 函数式接口 学习笔记

一, 函数式编程

java中的函数式编程体现就是Lambda和方法引用:

Lambda

// 1.1使用匿名内部类  
new Thread(new Runnable() {  
    @Override  
    public void run() {  
        System.out.println("Hello world !");  
    }  
}).start();  
  
// 1.2使用 lambda 获得Runnable接口对象  
new Thread(() -> System.out.println("Hello world !")).start();

Lambda除了简洁之外,还具有延迟执行特点

延迟执行

有些场景的代码执行后,结果不一定会被使用,从而造成性能浪费。而Lambda表达式是延迟执行的,这正好可以作为解决方案,提升性能。

public class Demo01Logger {
    private static void log(int level, String msg) {
        if (level == 1) {
            System.out.println(msg);
        }
     }
    public static void main(String[] args) {
        String msgA = "Hello";
        String msgB = "World";
        String msgC = "Java";
        log(2, msgA + msgB + msgC);//级别1 不一定能够满足 但是 字符串连接操作还是执行了 那么字符串的拼接操作就白做了,存在性能浪费
    }
}

Lambda的更优写法:

@FunctionalInterface
public interface MessageBuilder {
    String buildMessage();
}
public class Demo02LoggerLambda {
    private static void log(int level, MessageBuilder builder) {
        if (level == 1) {
            System.out.println(builder.buildMessage());// 实际上利用内部类 延迟的原理,代码不相关 无需进入到启动代理执行
        }
    }
    public static void main(String[] args) {
        String msgA = "Hello";
        String msgB = "World";
        String msgC = "Java";
       log(2,()->{
                System.out.println("lambda 是否执行了");
                return msgA + msgB + msgC;
        });
    }
}

方法引用

方法引用,不是方法调用!
方法引用是 lambda 表达式的语法糖,任何用方法引用的地方都可由lambda表达式替换

list.forEach(value -> System.out.println(value));

可替换为

list.forEach(System.out::println);
类别 使用形式
静态方法引用 类名 :: 静态方法名
实例方法引用 对象名(引用名) :: 实例方法名
类方法引用 类名 :: 实例方法名
构造方法引用 类名 :: new

二, 函数式接口

定义:函数式接口(Functional Interface):有且仅有一个抽象方法的接口,但可以有多个非抽象方法的接口

  • 你可以通过 Lambda 表达式或方法引用来创建该接口的对象。
  • 可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检测它是否是一个函数式接口

@FunctionalInterface

在JDK 8中引入了FunctionalInterface接口,其源代码定义如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

加上@FunctionalInterface标注,则会触发JavaCompiler的检查。对于符合函数接口的接口,加不加都无关紧要,但是加上则会提供一层编译检查的保障。如果不符合,则会报错。

需要注意的是:接口中只能存在一个抽象方法
格式:

修饰符 interface 接口名称{
    public abstract 返回值 方法名称(参数列表)
    // 其他方式 
}
// public abstract 可以不写 编译器自动加上
修饰符 interface 接口名称{
       返回值 方法名称(参数列表)
    // 其他方式 
}

调用举例:

@FunctionalInterface // 标明为函数式接口
public abstract MyFunctionInterface{
    void method(); //抽象方法
}

public class TestFunctional {
    // 定义一个含有函数式接口的方法
    public static void doSomething(MyFunctionInterface functionalInterface) {
        functionalInterface.method();//调用自定义函数式接口的方法
    }
    public static void main(String[] args) {
        //调用函数式接口的方法
        MyFunctionInterface functionalInterface = () -> System.out.println("hello!")
        doSomething(functionalInterface );
    }
}

常用函数式接口

接口 参数 返回值 说明
Supplier T 供给型;无参,返回一个指定泛型的对象
Consumer T 消费型;传入一个指定泛型的参数,无返回值
Predicate T Boolean 断言型;判断函数,返回判断结果true/false
Function T R 方法型;输入一个参数,得到一个结果

Supplier

无参有返回值

@FunctionalInterface
public interface Supplier {
    T get();
}

使用:

public class TestSupplier {
    public static void main(String[] args) {
         // 产生的数据作为 sout 作为输出
        Supplier supply = ()->"产生数据"
        System.out.println(supply.get());//输出“产生数据”
    }
}

Consumer

有参无返回值

@FunctionalInterface
public interface Consumer {
    void accept(T t);
    ...
}

使用:

public class TestComsumer {
    public static void main(String[] args) {
        Consumer consumer = s->System.out.println(s)
        consumer.accept("hello");//输出“hello”
    }
}

Predicate

对入参数据进行判断,并返回boolean

@FunctionalInterface
public interface Predicate {
    boolean test(T t);
    ...
}

使用:

public class UsePredicate {
    public static void main(String[] args) {
        Predicate predicate = (x)-> x==10;
        System.out.println(predicate.test(10));//输出true
    }
}

Function

将入参T转为返回值R

@FunctionalInterface
public interface Function {
    R apply(T t);
}

使用:

// 将数字转换为String类型
private static void numberToString() {
    String apply = function.apply(12);
    System.out.println("转换结果:"+apply);
}
public static void main(String[] args) {
        Function function = (s)->String.valueOf(s)
    System.out.println("转换结果:"+function.apply(12));//输出“12”
}

三, Functional Java

Functional Java是一个第三方库,是一个在Java语言中实现函数型编程范式的类库。

标准的Java 8 也引入了很多函数型编程范式的元素,比如Stream,lambda以及函数型接口。但在功能上Java 8 远不如Functional Java丰富,使用上也受到一定的限制。

Functional 项目地址:https://github.com/functionaljava/functionaljava

引入

//主包
compile "org.functionaljava:functionaljava:4.8"
//可以不引入
compile "org.functionaljava:functionaljava-java8:4.8"
compile "org.functionaljava:functionaljava-quickcheck:4.8"
compile "org.functionaljava:functionaljava-java-core:4.8"

F0, F, F2, …, F8

对应Fuction类, F输入类型为A,返回值类型为B
F0没有入参,F有1个入参,…,F8有8个入参
返回值类型都只有一个,最后那个类型参数代表返回值类型。

F twice = n -> n * 2;
F2 f = (a, b) -> a + b;
F3 g = (a, b, c) -> a + b + c;

Effect0, Effect1, Effect2, …, Effect8

没有返回值的函数接口类型, 对应Consumer
Effect0没有入参,Effect1有1个入参,…,Effect8有8个入参

Effect1 abc = n -> System.out.println(n);
FJ 接口 FJ 方法 Java 8 接口 Java 8 方法
Effect2 f BiConsumer accept
F2 f BiFunction apply
F2 f BinaryOperator apply
F2 f BiPredicate test
F0 f BooleanSupplier getAsBoolean

其他特性不多做介绍了。。。

你可能感兴趣的:(Java8 函数式接口 学习笔记)