Java8特性之函数式接口

1.接口interface

  • 新增函数式接口@FunctionalInterface,此接口为函数式接口,只能有一个抽象方法,用于在编译期间检查接口是否符合函数式接口的语法。主要方便直接用Lambda表达式构造出实例,让代码更加简洁。
  • 增加了default方法和static方法。default方法属于实例,声明对象后可调用;static方法属于类(接口),可以直接利用接口名调用。default方法为默认方法,有方法体,抽象类(abstract
    Class)或类(Class)实现此接口时可以覆写default方法。static方法是隶属于此接口的静态方法,和平常的static方法没区别。
//A接口
//此接口为函数式接口,只能有一个抽象方法
//用于在编译期间检查接口是否符合函数式接口的语法
@FunctionalInterface
public interface FunctionInterA {

    static String names = "张三";

    //默认方法,有方法体
    default String name(String name){
        return "早上好"+name;
    }

    //静态方法,有方法体
    static void close(){
        System.out.println("此方法不可变"+names);
    }

    //普通接口
    Integer age(int age);
}
  • 接口中的静态方法不会被继承,接口中的静态变量(static
    names=”张三”)会被继承。类或抽象类不能获得接口的static方法,只能通过FunctionInterA.close()获得,但是可以获得静态变量,即在类中可以访问names常量。
  • 如果一个抽象类或类实现多个接口且接口中有名称相同的方法(无论是普通方法还是default方法),类必须通过override覆写所有接口中同名的方法。
//B接口
@FunctionalInterface
public interface FunctionInterB {


    //默认方法,有方法体
    default String name(String name){
        return "中午好"+name;
    }

    Double money(double m);
}

在FunctionInterA和FunctionInterB中都有default方法name,让类实现这两个接口。

public class Test2 implements FunctionInterA,FunctionInterB{

    @Override
    public String name(String name){
        return "晚上好"+name;
    }

    @Override
    public Integer age(int age){
        return 1+age;
    };

    @Override
    public Double money(double m){
        return 2.2+m;
    }
    public static void main(String[] args) {
        FunctionInterA functionInterA = age -> 1+age;   //A接口实例
        FunctionInterB functionInterB = m -> 3.0+m;     //B接口实例
        Test2 test2 = new Test2();                      //类的实例
        System.out.println("A接口的默认方法为"+functionInterA.name("张三"));  
        System.out.println("B接口的默认方法为"+functionInterB.name("张三"));  
        System.out.println("类的name方法为"+test2.name(Test2.names));
    }
}

输出结果为:

A接口的默认方法为早上好张三
B接口的默认方法为中午好张三
类的name方法为晚上好张三

2.四大函数接口

四个函数式接口(@FunctionalInterface)分别为:Consumer< T>(消费型)、Supplier< T>(供给型)、Function<T,R>(函数型)、Predicate< T>(断言型)。

1.Consumer
  • Consumer< T>:消费型接口。接口方法 void accept(T
    t):参数类型是T,无返回值。由于输入时有参数,输出无返回值,可以理解为把参数给消费了,成为消费型接口。消费型接口代表了在一个输入参数上需要进行的操作。
@FunctionalInterface
public interface Consumer<T> {
 
    void accept(T t);
 
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
}

实例:函数式接口相当于把一个行为当作参数传入一个方法中,在Consumer的accept方法中没有返回值,需要对传入的参数做一些变化或者对传入参数与其他变量发生联系,否则就没有意义。Consumer作为一个参数,可以在accept方法的前后添加代码dosomething,在调用方法时,只需要利用Lambda表达式或匿名内部类重写accept方法即可,其他函数接口类似。

public class Test4 {

    public void encodePass(String str, Consumer<String> consumer){
        String s = str + "你好";
        consumer.accept(s);
    }

    public static void main(String[] args) {
        Test4 test4 = new Test4();
        String beforePass = "123561";
        System.out.println("加密前密码为"+beforePass);
        test4.encodePass(beforePass,(t)-> {
            try{
                System.out.println("机密后密码为"+DigestUtils.md5DigestAsHex(t.getBytes()));
            }catch (Exception e){
                e.printStackTrace();
            }
        });

    }
}

也可以直接用Consumer<类型>进行接收(单纯的重写accept方法),代码如下:

public class Test5 {
    public static void main(String[] args) {
        String beforePass = "15641864";
        System.out.println("加密前密码为"+beforePass);
        Consumer<String> consumer = t->{
            try{
                System.out.println("加密后密码为"+ DigestUtils.md5DigestAsHex(t.getBytes()));
            }catch (Exception e){
                e.printStackTrace();
            }
        };
        consumer.accept(beforePass);
    }
}
2.Supplier
  • Supplier< T>:供给型接口。接口方法 T
    get():无参数,返回T类型参数。由于没有输入,凭空能产生输出,新增了东西,成为供给型接口。供给型接口提供一个给定参数类型的结果。
@FunctionalInterface
public interface Supplier<T> {
    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

没有输入参数,产生一个随机值并输出:

public class Test6 {
    public static void main(String[] args) {
        Supplier<Double> integerSupplier = ()->Math.random();
        System.out.println("产生的随机数为"+integerSupplier.get());
    }
}
3.Function
  • Function<T,R>:函数型接口。接口方法R
    apply(T):对类型T参数操作,返回R类型参数。由于有输入参数T,也有输出值R,且输入和输出类型可以不同,类似于函数,称为函数接口。Function接口接收一个参数,并返回单一的结果。
@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

   default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

   static <T> Function<T, T> identity() {
        return t -> t;
    }
}

对一个字符串进行加密并获得加密后的值:

public class Test7 {
    public static void main(String[] args) {
        String beforePass = "asdasd";
        Function<String,String> function= (T)-> DigestUtils.md5DigestAsHex(T.getBytes());
        System.out.println("加密后密码为"+function.apply(beforePass));    
        function.apply(beforePass)为加密后的值,和Consumer不同
    }
}
4.Predicate
  • Predicate< T>:断言型接口。接口方法 boolean test(T t):对类型T进行条件筛选操作,返回boolean
@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    ...一些默认方法和静态方法...
}

获取字符串长度大于等于5的List集合,可以自定义test函数实现不同的功能。

public class Test8 {

    public List<String> filter(List<String> strings,Predicate<String> predicate){
        List<String> stringList = new ArrayList<>();
        for (String s:strings){
            if (predicate.test(s)){
                stringList.add(s);
            }
        }
        return stringList;
    }

    public static void main(String[] args) {
        Test8 test8 = new Test8();
        List<String> strings = Arrays.asList("aaaaa","sdd","sadasd","asdd","afasd");
        List<String> list = test8.filter(strings,t->t.length()>=5);
        System.out.println(list.toString());
    }
}

本人小白一个,如果有什么问题还请您在评论区留言!感谢

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值