JavaSE基础知识复习【15】

前言

肝开题报告

正文

1、函数式接口

  • 概念

函数式接口:有且只有一个抽象方法的接口,称之为函数式接口。当然接口中可以包含其他的方法(默认,静态,私有)
函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可
以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。

“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实
底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部
类的“语法糖”,但是二者在原理上是不同的

  • 格式
只要确保接口中有且仅有一个抽象方法即可:
修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容
}
注意:接口当中抽象方法的 public abstract 是可以省略的
  • @FunctionalInterface注解
一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。
需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。
作用:可以检测接口是否是一个函数式接口
     是:编译成功
     否:编译失败(接口中没有抽象方法或者抽象方法的个数不止一个)
  • 自定义函数式接口
    函数式接口的作用:一般可以作为方法的参数和返回值类型
public class Demo09FunctionalInterface {
	// 使用自定义的函数式接口作为方法参数
	private static void doSomething(MyFunctionalInterface inter) {
		inter.myMethod(); // 调用自定义的函数式接口方法
	} 
	public static void main(String[] args) {
	// 调用使用函数式接口的方法
		doSomething(()> System.out.println("Lambda执行啦!"));
	}
}

2、函数式编程

Lambda表达式作为方法参数和方法返回值

注意:Lambda表达式是延时执行的

如果抛开实现原理不说,Java中的Lambda表达式可以被当作是匿名内部类的替代品。
如果方法的参数是一个函数式接口类型,那么就可以使用Lambda表达式进行替代。使用Lambda表达式作为方法参数,其实就是使用函数式接口作为方法参数。
例如 java.lang.Runnable 接口就是一个函数式接口,假设有一个 startThread 方法使用该接口作为参数,那么就可以使用Lambda进行传参。这种情况其实和 Thread 类的构造方法参数为 Runnable 没有本质区别。

public class Demo01Runnable {
   public static void startThread(Runnable r) {
        new Thread(r).start();
    }
    public static void main(String[] args) {
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"-->线程启动了");
            }
        });
        
        startThread(() -> System.out.println(Thread.currentThread().getName() + "-->线程启动了"));
   }
}

类似地,如果一个方法的返回值类型是一个函数式接口,那么就可以直接返回一个Lambda表达式。当需要通过一个方法来获取一个 java.util.Comparator 接口类型的对象作为排序器时,就可以调该方法获取。

public class Demo02Comparator {
    //定义一个返回值类型使用函数式接口Comparator的方法
    public static Comparator<String> getComparator() {
        //字符串长度降序排序
        return (o1,o2)-> o2.length() - o1.length();
    }
    public static void main(String[] args) {
        String[] arr = {"aaa", "ccccc", "b", "bddc"};
        System.out.println(Arrays.toString(arr));
        Arrays.sort(arr, getComparator());
        System.out.println(Arrays.toString(arr));//[ccccc, bddc, aaa, b]
    }
}

3、常用函数式接口

Supplier接口

java.util.function.Supplier接口仅包含一个无参的方法:T get()。用来获取一个泛型参数指定类型的对象数据
Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据

public class Demo01Supplier {
    public static String getString(Supplier<String> su) {
        return su.get();
    }
    public static void main(String[] args) {
        //调用getString方法,方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
        String s = getString(() -> "胡歌");
        System.out.println(s);
   }
}

Consumer接口

java.util.function.Consumer接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定。
Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据
Consumer接口是一个消费型接口,泛型执行什么类型,就可以使用accept方法消费什么类型的数据
至于具体怎么消费(使用),需要自定义(输出,计算,…)

public class Demo01Consumer {
    public static void method(String name, Consumer<String> con) {
        con.accept(name);
    }
    public static void main(String[] args) {
        method("胡歌",(name)->{
            String s = new StringBuffer(name).reverse().toString();
            System.out.println(s);
        });
    }
}

Consumer接口的默认方法andThen
作用:需要两个Consumer接口,可以把两个Consumer接口组合到一起,再对数据进行消费
例如:
Consumer con1;
Consumer con2;
String s=“hello”;
con1.accept(s);
con2.accept(s);
改为连接两个Consumer接口,再进行消费
con1.andThen(con2).accept(s);谁写在前面谁先消费

public class Demo02AndThen {
    public static void method(String s, Consumer<String> con1, Consumer<String> con2) {
        //con1.accept(s);
        //con2.accept(s);

        //使用andThen方法,把两个Consumer接口连接到一起,再消费数据
        con1.andThen(con2).accept(s);
    }

    public static void main(String[] args) {
        //调用Method方法,传递一个字符串,两个Lambda表达式
        method("Hello", (s) -> {
            //消费方式,把字符串转为大写
            System.out.println(s.toUpperCase());
        }, (s) -> {
            //消费方式,把字符串转为小写
            System.out.println(s.toLowerCase());
        });
    }
}

Predicate接口

java.util.function.Predicate接口
作用:对某种数据类型的数据进行判断,结果返回一个boolean值
Predicate接口中包含一个抽象方法:
boolean test(T t):用来对指定数据类型数据进行判断的方法
    返回值:
      符合条件:返回true
      不符合条件:返回false

public class Demo01Predicate {
    public static boolean checkString(String s, Predicate<String> pre) {
        return pre.test(s);
    }
    public static void main(String[] args) {
        String s = "NING";
        boolean b = checkString(s, (str) -> str.length() > 5);
        System.out.println(b);//false
    }
}

既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个 Predicate 条件使用“与”逻辑连接起来实现“并且”的效果时,可以使用default方法 and

public class Demo02Predicate_and {
    public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2) {
        return pre1.and(pre2).test(s);
    }
    public static void main(String[] args) {
        String s = "5bcdde";
        boolean b=checkString(s,(s1)-> s1.length() > 5,(s2)-> s2.contains("a"));
        System.out.println(b);
    }
}

与 and 的“与”类似,默认方法 or 实现逻辑关系中的“或”

public class Demo03Predicate_or {
    public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2) {
        return pre1.or(pre2).test(s);
    }
    public static void main(String[] args) {
        String s = "s7777c";
        boolean b = checkString(s, s1 -> s1.length() > 5, s2 -> s2.contains("a"));
        System.out.println(b);
    }
}

“与”、“或”已经了解了,剩下的“非”(取反)也会简单。默认方法 negate

public class Demo04Predicate_negate {
    public static boolean checkString(String s, Predicate<String> pre) {
        //return !pre.test(s);
        return pre.negate().test(s);

    }
    public static void main(String[] args) {
        String s = "sbiBC";
        boolean b = checkString(s, s1 -> s.length() > 5);
        System.out.println(b);
    }
}

Function接口

java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件
Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果
使用的场景例如:将 String 类型转换为 Integer 类型

public class Demo01Function {
    public static void change(String s, Function<String, Integer> fun) {
        int in = fun.apply(s);
        System.out.println(in);
    }
    public static void main(String[] args) {
        String s = "239244489";
        //传递字符串类型的整数和Lambda表达式
        change(s,(String str)->{
            return Integer.parseInt(str);
        });
        //优化Lambda表达式
        change(s, str-> Integer.parseInt(str));
    }
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:白松林 返回首页