Java8 新特性——函数式接口

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

函数式接口可以被隐式转换为 lambda 表达式。

@FunctionalInterface注解 

该注解可以用来检测该接口是否为函数式接口,将该注解放在 接口定义的上方,如果接口是函数式接口,编译通过;如果不是,编译失败

需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。

函数式接口的使用 

作为方法的参数进行使用

/*
 * 函数式接口作为方法的参数进行使用
*/
public class Test {

    //定义一个方法threadStart,参数使用函数式接口Runnable
    public static void threadStart(Runnable runnable){
        new Thread(runnable).start();
    }
​
    public static void main(String[] args) {
        //调用threadStart方法,方法的参数是一个接口,可以传递这个接口的匿名内部类
        threadStart(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"开启线程");
            }
        });
        //使用Lambda表达式优化
        threadStart(()->System.out.println(Thread.currentThread().getName()+"开启线程"));
    }
}

 作为返回值进行使用

/*
 * 函数式接口作为返回值进行使用
 */
public class Test {
    //定义一个方法,返回值类型为使用函数式接口Comparator
    public static Comparator<String> getComparator(){
        /*方法的返回值类型是一个接口,那么我们可以返回这个接口的匿名内部类
        return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 按照字符串的长度降序排序
                return o2.length()-o1.length();
            }
        };
        */
        //由于返回值类型是一个函数式接口可以返回一个Lambda表达式
        return ((o1, o2) -> o2.length()-o1.length());
    }
​
    public static void main(String[] args) {
        String[] arr={"aa", "a", "aaa"};
        Arrays.sort(arr,getComparator());
        for (String s : arr) {
            System.out.println(s);
        }
    }
}

常用函数式接口

Supplier接口

java.util.function.Supplier <T>接口仅包含一个无参的方法:T get(),用来获取一个泛型参数指定类型的对象数据

该接口被称为生产型接口,指定接口的泛型是什么类型,那么get方法就会产生什么类型的数据

抽象方法get

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Supplier;
​
/*
    java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get(),用来获取一个泛型参数指定类型的对象数据
    Supplier<T> 接口被称为生产型接口,指定接口的泛型是什么类型,那么get方法就会产生什么类型的数据
 */
public class Demo04SupplierGet {
    //定义一个方法,方法的参数传递Supplier<T>接口,泛型执行String,get方法就返回一个String
    public static String getString(Supplier<String> sup){
        return sup.get();
    }
​
    public static void main(String[] args) {
        //调用getString方法,参数是一个函数式接口可以使用Lambda表达式
        String s = getString(() -> "hs-vae");
        System.out.println(s);
    }
}

Consumer接口介绍

java.util.function.Consumer<T>接口与Supplier接口相反,被称之为消费型接口,它不是生产一个数据,而是消费一个数据,其数据类型由指定的泛型决定

该接口包含抽象方法void accept(T t),作用是消费一个指定泛型的数据,消费是自定义的(输出、计算....)

抽象方法accept

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Consumer;
​
/*
     java.util.function.Consumer<T> 接口与Supplier接口相反,被称之为消费型接口,它不是生产一个数据,而是消费一个数据,其数据类型由指定的泛型决定
     该接口包含抽象方法void accept(T t),作用是消费一个指定泛型的数据,消费是自定义的(输出,计算....)
 */
public class Demo05ConsumerAccept {
    //定义一个方法,方法的参数传递一个姓名和泛型为String的Consumer接口,可以使用该接口消费姓名
    public static void show(String name, Consumer<String> cs){
        cs.accept(name);
    }
​
    public static void main(String[] args) {
        //调用show方法,参数里面包含函数式接口Consumer可以使用Lambda表达式
        //消费方式:输出姓名
        show("许嵩", System.out::println);
        //消费方式:反转姓名并输出
        show("许嵩",(String name)->{
            String s = new StringBuffer(name).reverse().toString();
            System.out.println(s);
        });
    }
}
​
//输出结果
许嵩
嵩许

默认方法andThen

该方法需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Consumer;
​
/*
    andThen方法需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费
    例如:
    Consumer<String> con1
    Consumer<String> con2
    String s = "hs-vae";
    连接两个Consumer接口,再进行消费
    con1.andThen(con2).accept(s); 谁先写在前边谁先消费
 */
public class Demo06ConsumerAndThen {
    //定义一个方法,方法的参数传递一个字符串和两个Consumer接口
    public static void show(String s, Consumer<String> con1,Consumer<String> con2){
        //使用andThen方法,把con1和con2两个接口连接到一起,再消费数据(先执行con1再执行con2)
        con1.andThen(con2).accept(s);
    }
​
    public static void main(String[] args) {
        //调用show方法,传递一个字符串,可以使用两个Lambda表达式
        show("Hello",
                (t)->{
                    //消费方式:把字符串转换为大写输出
                    System.out.println(t.toUpperCase());
                },
                (t)->{
                    //消费方式:把字符串转换为小写输出
                    System.out.println(t.toLowerCase());
                });  
    }
}
​
//输出结果
HELLO
hello

Predicate接口介绍

当我们需要对某种类型的数据进行判断,从而得到一个boolean值结果,这时可以使用java.util.function.Predicate<T> 接口

抽象方法test

boolean test(T t):用来对指定数据类型数据进行判断的方法

符合条件,返回true

不符合条件,返回false

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Predicate;
​
/*
    java.util.function.Predicate<T> 接口
    作用:对某种数据类型的数据进行判断,结果返回一个boolean值
​
    Predicate接口中包含一个抽象方法:
      - boolean test(T t):用来对指定数据类型数据进行判断的方法
        符合条件,返回true
        不符合条件,返回false
 */
public class Demo07PredicateTest {
    //定义一个方法,参数传递一个字符串和Predicate接口,使用接口中的test方法进行判断,并返回结果
    public static boolean checkString(String s, Predicate<String> p){
        return p.test(s);
    }
​
    public static void main(String[] args) {
        //定义一个字符串
        String s = "hs-vae";
        //调用checkString方法对字符串进行校验,参数中包含Predicate接口可以使用Lambda表达式
        //校验规则为该字符串的长度是否大于5
        boolean b = checkString(s, (t) -> t.length() > 4);
        System.out.println(b);  //true
    }
}

默认方法and

给出一个案例

需求为:判断一个字符串,有两个判断的条件,第一判断字符串的长度是否大于5,第二字符串是否包含'a' ,两个条件必须同时满足返回true

按照往常可以使用逻辑运算符&&连接两个条件

不过Predicate接口中有一个默认方法and,表示并且关系,也可以用于连接两个判断条件

该方法内部的两个判断条件就是使用逻辑运算符&&连接起来的

使用如下

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Predicate;
​
/*
    案例需求:
    判断一个字符串,有两个判断的条件,条件一判断字符串的长度是否大于5,条件二字符串是否包含'a' ,两个条件必须同时满足时返回true
​
    可以使用Predicate接口中的默认方法and
    该方法的源码就是两个判断条件通过逻辑运算符&&(且)连接的
 */
public class Demo08PredicateAnd {
    //定义一个方法,方法的参数传递一个字符串和两个Predicate接口(用于判断两个条件,必须同时成立)
    public static boolean checkString(String s, Predicate<String> p1,Predicate<String> p2){
        return p1.and(p2).test(s); //等同于return p1.test(s)&& p2.test(s)
    }
​
    public static void main(String[] args) {
        //调用checkString方法,参数传递两个Predicate接口,可以使用两个Lambda表达式
        //一个判断字符串长度是否大于5,另一个判断字符串是否包含'a',仅当同时满足时为返回true
        boolean b = checkString("hs-vae", (t) -> t.length() > 5, (t) -> t.contains("a"));
        System.out.println(b);    //true
    }
}

默认方法or

给出一个案例

需求为:判断一个字符串,有两个判断的条件,第一判断字符串的长度是否大于5,第二字符串是否包含'a' ,当满足一个条件时返回true

按照往常可以使用逻辑运算符||连接两个条件

不过Predicate接口中有一个默认方法or,表示或关系,也可以用于连接两个判断条件

or方法内部的两个判断条件就是使用逻辑运算||符连接起来的

使用如下

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Predicate;
​
/*
    案例需求:
    判断一个字符串,有两个判断的条件,条件一判断字符串的长度是否大于5,条件二字符串是否包含'a' ,一个条件成立时返回true
​
    可以使用Predicate接口中的默认方法or
    该方法的源码就是两个判断条件通过逻辑运算符||(或)连接的
 */
public class Demo09PredicateOr {
    //定义一个方法,方法的参数传递一个字符串和两个Predicate接口(用于判断两个条件,一个条件成立即可)
    public static boolean checkString(String s, Predicate<String> p1, Predicate<String> p2){
        return p1.or(p2).test(s); //等同于return p1.test(s)|| p2.test(s)
    }
​
    public static void main(String[] args) {
        //调用checkString方法,参数传递两个Predicate接口,可以使用两个Lambda表达式
        //一个判断字符串长度是否大于5,另一个判断字符串是否包含'a',仅当同时满足时为返回true
        boolean b = checkString("vae", (t) -> t.length() > 5, (t) -> t.contains("a"));
        System.out.println(b);    //true
    }
}
​

默认方法negate

给出一个案例

需求为:判断一个字符串的长度是否大于5,如果字符串长度大于5返回false,反之返回true

可以使用取反符号!对判断的结果进行取反

也可以使用Predicate接口中的默认方法negate,也表示取反的意思

使用如下

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Predicate;
​
/*
    案例需求: 判断一个字符串的长度是否大于5
    如果字符串长度大于5返回false,反之返回true
    可以使用取反符号!对判断的结果进行取反
​
    Predicate接口中的默认方法negate,也表示取反的意思
    default Predicate<T> negate(){
        return (t) -> !test(t);
    }
 */
public class Demo10PredicateNegate {
    //定义一个方法,参数传递一个字符串和一个Predicate接口(判断字符串长度是否大于5)
    public static boolean checkString(String s , Predicate<String> p){
        return p.negate().test(s); //等同于return !p.test(s);
    }
​
    public static void main(String[] args) {
        //调用checkString方法,参数传递了一个Predicate接口,可以使用Lambda表达式
        boolean b = checkString("vae", (t) -> t.length() > 5);
        System.out.println(b);   //true
    }
}

Function接口介绍

java.util.function.Function<T,R> 接口为一个转换类型的接口,用来根据一个类型的数据得到另一个类型的数据,T称为前置条件,

R称为后置条件

抽象方法apply

Function接口中抽象方法为:R apply (T t),根据类型T的参数获取类型R的结果

给出案例

需求:将String类型转换为Integer类型

实现如下

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Function;
​
public class Demo11FunctionApply {
    /*
        定义一个方法,参数传递一个字符串类型的整数和一个Function接口
        使用Function接口中的方法apply,把字符串类型的整数转换为Integer类型的整数
     */
    public static void change(String s, Function<String,Integer> f){
        Integer i = f.apply(s);
        System.out.println(i);
    }
​
    public static void main(String[] args) {
        //调用change方法,传递字符串类型的整数,和Lambda表达式
        change("123456",(s)->Integer.parseInt(s));
    }
}
​

默认方法andThen

Function接口中的默认方法andThen,用来进行组合操作

给出案例

需求:把String类型的"123456",转换为Integer类型并且加10,再转换为String类型

实现如下

package com.hs_vae.FunctionalInterface;
​
import java.util.function.Function;
​
/*
     案例需求:把String类型的"123456",转换为Integer类型并且加10,再转换为String类型
 */
public class Demo12FunctionAndThen {
    /*
       定义一个方法,参数传递一个字符串类型的整数和两个Function接口
       一个接口泛型为<String,Integer>
       另一个接口泛型为<Integer,String>
     */
    public static void change(String s, Function<String,Integer> f1,Function<Integer,String> f2){
        String result = f1.andThen(f2).apply(s);
        System.out.println(result);
    }
​
    public static void main(String[] args) {
        //调用change方法,传递一个字符串类型的整数和两个Lambda表达式
        change("10",s -> Integer.parseInt(s)+10,i -> i+"");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值