一、函数式接口概念
1、什么是函数式接口:有且仅有一个抽象方法的接口。
Java中的函数式编程体现的就是Lambda表达式,所以函数式接口通常使用到Lambda表达式。
2、使用案例
(1)创建一个接口:Interface MyInterface()
public interface MyInterface {
void test();
}
(2)创建一个测试类:MyInterfaceDemo
public class MyInterfaceDemo {
public static void main(String[] args) {
// Lambda表示式实现接口
MyInterface my = () -> {
System.out.println("实现了test()方法");
};
my.test();
}
}
这样使用Lambda表达式很方便的实现了接口中的test()方法,省下了“实现类”的操作。
3、函数式接口——应用场景
(1)作为方法的参数
public class RunnableDemo {
public static void main(String[] args) {
// Lambda表达式
startThread(()-> System.out.println(Thread.currentThread().getName()+",线程启动了"));
// 匿名内部类
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+",线程启动了");
}
});
}
// 待会会在主函数中使用Lambda实现Runnable类的抽象方法
private static void startThread(Runnable r){
Thread t = new Thread(r);
t.start();
}
(2)作为方法的返回值
使用前提:该方法的返回值是函数式接口。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ComparatorDemo {
public static void main(String[] args) {
// 创建集合
List<String> list = new ArrayList<>();
// 添加元素
list.add("a");
list.add("bbb");
list.add("cc");
list.add("dddddd");
list.add("eeee");
System.out.println("调用前:"+list);
Collections.sort(list,getComparator());
System.out.println("调用后:"+list);
}
// 匿名内部类实现
/*public static Comparator<String> getComparator(){
return new Comparator<String>(){
@Override
public int compare(String s1, String s2) {
// 根据长度进行比较
return s1.length()-s2.length();
}
};
}*/
// Lambda实现
public static Comparator<String> getComparator(){
return (s1, s2) -> s1.length()-s2.length();
}
}
二、函数式接口——Supplier接口
1、Supplier接口方法
Supplier<T>: 包含一个无参的方法
- T get(): 获得结果
- 该方法不需要参数,它会按照某种实现逻辑(由我们使用Lambda表达式实现)返回一个数据。
- Supplier<T> 接口也被成为生产型接口,你给它什么类型的数据,那它就会返回对应类型的数据供我们使用。
2、使用案例
import java.util.Arrays;
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
// Lambda表达式实现Supplier接口方法
Integer num = getInteger(() -> 30);
System.out.println(num);
// 定义数组
int[] arr = {36,68,98,54,21,12,69};
// Lambda表达式获得最大值
Integer max = getMax(() -> {
Arrays.sort(arr);
return arr[arr.length-1];
});
System.out.println(max);
}
// 定义一个方法,返回一个整数数据
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
// 获得数组中的最大值
public static Integer getMax(Supplier<Integer> sup){
return sup.get();
}
}
三、函数式接口——Consumer接口
1、接口的作用:接受单个参数并且不返回结果的操作。(其实说白了该接口就是只负责处理数据,而不返回结果,这就是消费型。)
2、方法:
- void accept(T t):对给定的参数执行操作(具体是什么操作,可以由我们重写方法实现)
- default Consumer<T> andThen(Consumer after):返回一个组会的Consumer操作,依次执行操作,然后执行after操作。这个说的比较术语,其实说白了就是依次执行操作,比如a.andThen(b),那么就先执行a.accept()操作再执行b.accept()操作 (a和b都是Consumer对象。)
3.使用案例
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
// 定义字符串数组
String[] strArray = {"林青霞,30","张曼玉,35","王祖贤,33"};
// Lambda表达式重写方法
printValue(strArray,
s-> System.out.print("姓名:"+s.split(",")[0]),
s -> System.out.println(",年龄:"+s.split(",")[1])
);
// Lambda表达式重写方法
operatorString("奥特曼",s -> System.out.println(s));
}
// 定义一个方法,输出数组中的每对字符串,要求格式:姓名:xx,年龄:xx
public static void printValue(String[] strArray, Consumer<String> con1, Consumer<String> con2){
for (String s : strArray) {
con1.andThen(con2).accept(s);
}
}
// 定义一个方法,消费一个字符串数据
private static void operatorString(String name,Consumer<String> con){
con.accept(name);
}
}
四、函数式接口——Predicate接口
1、接口的作用:Predicate,这个单词意思就是预测,顾名思义该接口的作用就是对给定的参数进行判断,返回值的boolean值。
2、方法
- boolean test(T): 对给定的参数进行判断。(判断的内容由我们用Lambda表达式实现)
- default Predicate<T> negate(): 逻辑非。表示逻辑的否定
- default Predicate<T> and(Predicate other):逻辑短路与,返回一个组合判断。
- default Predicate<T> or(Predicate other):逻辑短路或,返回一个组合判断。
- Predicate<T> 接口通常用于判断参数是否满足指定的条件。
3、使用案例
package Test;
import java.util.ArrayList;
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
// Lambda表达式重写方法
boolean result1 = checkString("hello", s -> s.length() > 8);
System.out.println(result1);
// Lambda表达式重写方法
boolean result2 = checkString("铠甲勇士vs奥特曼", s -> s.length() > 8, s -> s.length() < 15);
System.out.println(result2);
/**
* 字符串数组中有多条信息,
* 请通过Predicate接口的拼接将符合要求的字符串筛选到集合ArrayList集合
* 要求如下:
* 1.姓名长度大于2
* 2年龄大于33
*/
ArrayList<String> list = Test(s -> s.split(",")[0].length() > 2, s -> Integer.parseInt(s.split(",")[1]) > 33);
for (String s : list) {
System.out.println(s);
}
}
// 判断给定的字符串是否满足要求
private static boolean checkString(String s,Predicate<String> pre){
return pre.test(s);
}
// 同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
private static boolean checkString(String s,Predicate<String> pre1, Predicate<String> pre2){
/*boolean result1 = pre1.test(s);
boolean result2 = pre2.test(s);
boolean b = result1 && result2;*/
boolean b = pre1.and(pre2).test(s);
return b;
}
// 筛选姓名长度大于2;年龄大于33
private static ArrayList<String> Test(Predicate<String> pre1, Predicate<String> pre2){
// 数据
String[] strArray = {"林青霞,30","柳岩,34","张曼玉,40","火龙果,83","姑奶奶,18"};
// 创建集合
ArrayList<String> list = new ArrayList<>();
// 筛选数据
for (String s : strArray) {
boolean result = pre1.and(pre2).test(s);
if (result)
list.add(s);
}
return list;
}
}
五、函数式接口——Function接口
1、接口的作用:接受一个参数并返回一个结果。
2、接口类型:public interface Function<T,R>
Function<T,R>中的T,R是啥东东嘞?
3、方法:
4、使用案例:
package Test;
import java.util.function.Function;
public class FunctionDemo {
public static void main(String[] args) {
convert("100", s -> Integer.parseInt(s));
convert(300,num-> String.valueOf(num+300));
convert("99",s -> Integer.parseInt(s),num->String.valueOf(num+900));
}
// 定义一个方法,把一个字符串转换成int类型,并在控制台输出
public static void convert(String s, Function<String,Integer> fun){
Integer number = fun.apply(s);
System.out.println(number);
}
// 定义一个方法,把一个int类型的数据加上一个整数之后,转化成字符串在控制台输出
public static void convert(Integer num,Function<Integer,String> fun){
String str = fun.apply(num);
System.out.println(str);
}
// 定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数之后,转为字符串在控制台输出
public static void convert(String s,Function<String,Integer> fun1, Function<Integer,String> fun2){
Integer num = fun1.apply(s);
String str = fun2.apply(num);
System.out.println(str);
}
}