常用的函数式接口:
1、Supplier接口:java.util.function.Supplier< T >
java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get()
用来获取一个泛型参数指定类型的对象数据。
Suppelier<T> 接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据
代码演示:
import java.util.function.Supplier;
public class SupplierDemo {
//接口指定泛型String类,方法get返回值就是String类型
public static String getString(Supplier<String> supplier){
return supplier.get();
}
public static void main(String[] args) {
String str = getString(() -> {
return "hello java";
});
System.out.println(str);
}
}
练习: 求数组中的最大值,使用Supplier接口作为方法参数类型,通过Lambda表达式求出int数组中的最大值。
代码演示:
import java.util.function.Supplier;
public class SupplierTest {
public static int getMax(Supplier<Integer> supplier){
return supplier.get();
}
public static void main(String[] args) {
int[] arr = {-1, -9, 20, 23, 54, -30, -78, 996};
//方法的参数是一个函数式接口,使用Lambda表达式获取最大值
int maxValue = getMax(() -> {
//获取数组的最大值
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
});
System.out.println("maxValue=" + maxvalue);
}
}
执行结果:
2、Consumer接口:java.util.funcation.Consumer< T >
java.util.funcation.Consumer<T> 接口正好和接口Supplier相反;
它是负责消费一个数据,数据类型由泛型决定;
Consumer接口中的抽象方法void accept(T t) , 意思是消费一个指定的反泛型数据。
代码演示:
import java.util.function.Consumer;
public class ConsumerDemo {
/*
定义一个方法,方法的参数1传递一个字符串的姓名
方法的参数2传递Consumer接口,泛型使用String类型
使用Consumer接口消费字符串姓名
*/
public static void consumerStr(String name,Consumer<String> consumer){
//Consumer接口中的方法accept意思是消费一个指定的泛型数据
consumer.accept(name);
}
public static void main(String[] args) {
consumerStr("Lebron",(String name)->{
//对传入的数据进行消费
StringBuffer reverse = new StringBuffer(name).reverse();
System.out.println(reverse);
});
}
}
执行结果:
Consumer接口中的默认方法:andThen
Consumer接口中的默认方法:andThen
如果一个方法的参数和返回值类型都是Consumer类型,那么就可以实现效果:
在消费数据的时候,首先做一个操作,然后在做一个操作,实现组合。
代码演示:
import java.util.function.Consumer;
/**
* Consumer接口中的方法andThen
* 作用:把两个Consumer接口组合到一起,再对数据进行消费
* 比如:
* Consumer con1
* Consumer con2
* String s
* con1.accept(s)
* con2.accept(s)
* 这段代码使用andThen方法优化,将两个Consumer组合到一起,
* 再对数据进行消费
* con1.andThen(con2).accept();
*/
public class ConsumerDemo1 {
public static void method(String str, Consumer<String> con1, Consumer<String> con2) {
/*不使用andThen
con1.accept(str);
con2.accept(str);*/
//使用andThen
con1.andThen(con2).accept(str);
}
public static void main(String[] args) {
method("hello JavA",
(t)->{
System.out.println(t.toUpperCase());
},
(t)->{
System.out.println(t.toLowerCase());
}
);
}
}
执行结果:
练习:
一个字符串数组中存有多条信息,按照格式 :姓名:XX ,年龄:xx 的格式将信息打印出来。
要求将打印姓名的动作作为第一个Consumer接口中的 Lambda 实例。
将打印性别的动作作为第二个Consumer接口的Lambda实例。
将两个Consumer接口按照顺序拼接到一起
代码演示:
import java.util.function.Consumer;
public class ConsumerTest {
/**
* 定义方法对字符串进行消费
*
* @param arr 字符串数组
* @param con1 第一个Consumer接口
* @param con2 第二个Consumer接口
*/
public static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2) {
for (String msg : arr) {
con1.andThen(con2).accept(msg);
}
}
public static void main(String[] args) {
String[] infoArr = {"Kobe,39", "Lebron,35", "Durant,32", "Curry,31"};
printInfo(infoArr,
(msg) -> {
//对姓名进行切割打印
String name = msg.split(",")[0];
System.out.print("姓名:" + name+" ");
},
(msg) -> {
//对性别进行打印
String age = msg.split(",")[1];
System.out.println("年龄:" + age);
});
}
}
执行结果:
3、Predicate接口:java.util.function.Predicate< T >
抽象方法:test< T t > 方法:
Predicate接口中的抽象方法:boolean test<T t> 用于判断传入的参数t是否为定义的泛型类型。
代码演示:
/**
* 方法test用来检测指定的数据是否符合泛型
* 返回值 true:符合 false:不符合
*/
public class PredicateDemo {
/**
* @param string 要检测的数据
* @param predicate 用于检测的接口,泛型是String类型
* @return 返回值true或false
*/
public static boolean checkStr(String string, Predicate<String> predicate){
return predicate.test(string);
}
public static void main(String[] args) {
boolean b = checkStr("hello java", (String str) -> {
//判断字符串长度是否大于5
return str.length() > 5;
});
System.out.println(b);
}
}
默认方法:and
Predicate 中的方法 and 用于判断条件,表示并且关系,可以用于连接两个判断条件
代码演示:
import java.util.function.Predicate;
/**
* 需求:传递一个字符串
* 有两个条件
* 1:判断字符串的长度是否大于5;
* 2:判断字符串是否以a字符开头
*/
public class PredicateDemo1 {
/**
* 判断字符串的方法
*
* @param str 指定的字符串
* @param pre1 传入的第一个接口
* @param pre2 传入的第一个接口
* @return boolean 类型的返回值
*/
public static boolean checkStr(String str, Predicate<String> pre1, Predicate<String> pre2) {
return pre1.and(pre2).test(str);
}
public static void main(String[] args) {
String str = "abcdefgh";
boolean b = checkStr(str, (String s) -> {
return s.length() > 5;
}, (String s) -> {
return s.startsWith("a");
});
System.out.println(b);
}
}
默认方法 or 和 negate
Predicate 接口中的方法or: 或运算,用于两个来判断条件,用法和and类似;
negate : 返回一个表示该谓词的逻辑否定的谓词,其实就是取反运算。
练习: 数组中有多条" 姓名+ 年龄 " 的信息,通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,
筛选条件:1、名字长度大于4;2、年龄大于30。
代码演示:
import java.util.ArrayList;
import java.util.function.Predicate;
/*
数组中有多条" 姓名+ 年龄 " 的信息,
通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,
筛选条件:1、名字长度大于4;2、年龄大于30。
*/
public class PredicateTest {
/**
* 定义方法筛选符合名字和年龄符合要求的信息
*
* @param infoArr 信息数组
* @param pre1 用于筛选第一个条件的接口参数
* @param pre2 用于筛选第二个条件的接口参数
* @return 返回一个包含符合条件的集合
*/
public static ArrayList<String> filterStr(String[] infoArr, Predicate<String> pre1,
Predicate<String> pre2) {
ArrayList<String> list = new ArrayList<>();
for (String string : infoArr) {
boolean b = pre1.and(pre2).test(string);
//如果b==true
if (b) {
list.add(string);
}
}
return list;
}
public static void main(String[] args) {
String[] infoArr = new String[]{"Lebron,35", "Curry,29", "Durant,32", "Harden,28", "paul,34"};
ArrayList<String> list = filterStr(infoArr,
(String str) -> {
return str.split(",")[0].length() >= 5;
},
(String str) -> {
return str.split(",")[1].startsWith("3");
});
for (String s : list) {
System.out.println(s);
}
}
}
执行结果:
4、Function 接口
java.util.function.Function< T, R >
这个接口用来根据一个类型的数据得到另一个类型的数据,
前面的泛型称之为前置条件,后面的泛型称之为后置条件。
默认方法:R apply(T t),根据类型参数 T 获取类型 R 的结果
代码演示:
import java.util.function.Function;
/**
* Function接口中的方法: R apply(T t)
* 根据参数T得到类型为R的结果
* 使用场景:
* 比如将字符串类型的整数,转换为Integer类型的整数
*/
public class FunctionDemo1 {
/**
* 定义方法把类型为String类型的整数转换为Integer
*
* @param str 传入的字符串整数
* @param function 接口Function 泛型分别为String和Integer
* @return 返回转换后的Integer整数
*/
public static void changeStr(String str, Function<String, Integer> function) {
Integer integer = function.apply(str);
System.out.println(integer);
}
public static void main(String[] args) {
String str = new String("11235813");
changeStr(str, (String string) -> {
return Integer.parseInt(string);
});
//优化Lambda表达式
changeStr(str, string -> Integer.parseInt(string));
}
}
默认方法 andThen:用来进行组合操作
需求:把String类型的 “123” 转换为Integer,再把转换后的数据加13;再把增加后的Integer数据转换为String类型
代码演示:
import java.util.function.Function;
public class FunctionTest {
/**
* 把String转换为Integer,再把Integer转换为String的方法
*
* @param str 字符串整数
* @param fun1 把String转换为Integer的接口
* @param fun2 把Integer转换为String的接口
*/
public static void change(String str, Function<String, Integer> fun1, Function<Integer, String> fun2) {
String s = fun1.andThen(fun2).apply(str);
System.out.println(s);
}
public static void main(String[] args) {
String string = "1234";
change(string,
(String s) -> {
return Integer.parseInt(s) + 13;
},
(Integer i) -> {
return String.valueOf(i);
});
}
}
执行结果: