1.背景:面向对象中方法不是一等公民,不能将方法传入到一个参数中,必须使用对象作为一个载体传递进去;但是这种方式不优雅,在有些语言中的高阶函数中支持一个函数作为一种行为传递到另一个函数当中,但是java不支持这种方式,于是就通过一个接口,将接口的实现类传递进去。

2.常见的函数式接口

@FuctionalInterface

//1.
public interface Consumer<T> {
    void accept(T t);//消费者函数式接口,这个方法无返回值,只是将数据消费掉;
}

//2.
public interface Supplier<T> {

    T get();//无参数,但是有返回值;
}


//3.
public interface Predicate<T> {

    boolean test(T t);//断言函数式接口,判断传入的t是否满足条件,满足:True
}

//4.函数

public interface Function<T, R> {//函数,数据转化,例如将所有的小写字母变为大写字母就可以,步骤:实现Function接口,并且重写apply方法即可。

    R apply(T t);
}

例如:函数式接口之Function


package com.ydlclass.feature;

import java.util.Locale;
import java.util.function.Function;

public class ToUpper implements Function<String,String> {
    @Override
    public String apply(String s) {
        return s.toUpperCase();//Function作为一种转化数据的接口,也可以用于类型的转换
    }


    public static void main(String[] args) {
        String abc = new ToUpper().apply("abc");
        System.out.println(abc);//方式1,通过创建一个类,实现Function接口,实现接口的方法再实例化对象后,调用方法


        //2.使用匿名内部类的方式实现,有时这个功能可能只需要使用一次即可,可以使用匿名内部类实现;
        //本质上依旧是一个实现Function接口的类,只不过这个类没有名称,并且使用固定的语法表示
        Function<String,String> function = new Function<String,String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        };
        System.out.println(function.apply("abc"));

        //对于匿名内部类,并且这个类是实现了函数式接口的匿名内部类,就可以简化成函数式编程;
        Function<String,String> function1 = (s) -> s.toUpperCase();
        System.out.println(function1.apply("abc"));


    }
}



例如:函数式接口之Consumer


package com.ydlclass.feature;

import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.Function;

public class ToUpper implements Function<String,String> {
    @Override
    public String apply(String s) {
        return s.toUpperCase();//Function作为一种转化数据的接口,也可以用于类型的转换
    }


    public static void main(String[] args) {
        Consumer<String> consumer1 = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer1.accept("abc");

        Consumer<String> consumer = c -> System.out.println(c);
        consumer.accept("abc");


        //如果上面的方法体中只有一句话,只是调用某个类的方法,方法中只有这个参数,那么参数也可以不写,逗号换成冒号

        Consumer<String> consumer2 = System.out::println;//最简洁的函数式编程,(c)-> 都可以不写
        consumer2.accept("abc");

        Consumer<String> consumer3 = (c) -> System.out.println(c +  "被消费了");//此时就不能写成最简单的函数式编程的样子
        consumer3.accept("abc");

    }
}


例如:例如:函数式接口之Supplier


package com.ydlclass.feature;

import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class ToUpper implements Function<String,String> {
    @Override
    public String apply(String s) {
        return s.toUpperCase();//Function作为一种转化数据的接口,也可以用于类型的转换
    }


    public static void main(String[] args) {
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "supplier";
            }
        };
        System.out.println(supplier.get());

        Supplier<String> supplier1 = () -> "supplier";
        System.out.println(supplier1.get());

        

    }
}


例如:例如:函数式接口之Predicate

package com.ydlclass.feature;

import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public class ToUpper implements Function<String,String> {
    @Override
    public String apply(String s) {
        return s.toUpperCase();//Function作为一种转化数据的接口,也可以用于类型的转换
    }


    public static void main(String[] args) {
        Predicate<String> predicate = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("a");
            }
        };

        System.out.println(predicate.test("abc"));


        Predicate<String> predicate1 = (s) -> s.contains("a");
        System.out.println(predicate1.test("abc"));


    }
}



3.Stream编程最重要的就是操纵数据,例如消费数据,(有接收值无返回值)