Java系列之:函数式接口
- 一、函数式接口
- 二、函数式接口作为方法的返回值
- 三、Supplier接口
- 四、Supplier接口获取数组最大值
- 五、Consumer接口
- 六、Consumer接口案例
- 七、Predicate接口
- 八、Predicate接口案例
- 九、Function接口
- 十、Function接口案例
一、函数式接口
函数式接口:
- 有且仅有一个抽象方法的接口
- Java中的函数式编程体现就是Lambda表达式,所以函数式接口可以适用于Lambda使用的接口
- 只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利进行推导
定义函数式接口:
- @FunctionalInterface
- 放在接口定义的上方:如果接口是函数式接口,编译通过,如果不是,编译失败
注意:
- 定义函数式接口,@FunctionalInterface接口是可选的,不写这个注释,只要保证满足函数式接口定义的条件,也照样是函数式接口,建议加上该注解。
函数式接口作为方法的参数:
- 方法的参数是一个函数式接口,可以使用Lambda表达式作为参数传递
public interface SubString {
String mySubString(String s,int x,int y);
}
public class ConvertDemo {
public static void main(String[] args) {
useConverter((String s,int x,int y) -> {
return s.substring(x,y);
});
useConverter((s,x,y) -> s.substring(x,y));
//引用类的实例方法
useConverter(String::substring);
}
public static void useConverter(SubString c){
String s = c.mySubString("HelloWorld", 2, 5);
System.out.println(s);
}
}
二、函数式接口作为方法的返回值
- 定义一个类,提供两个方法
- 一个方法是Comparator getComparator()方法返回值Comparator是一个函数式接口
- 一个方法是主方法,在主方法中调用getComparator方法
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class ComparatorDemo {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("cccc");
strings.add("bb");
strings.add("ffffff");
strings.add("ggg");
strings.add("h");
System.out.println("排序前:" + strings);
Collections.sort(strings,getComparator());
System.out.println("排序后:" + strings);
}
private static Comparator<String> getComparator(){
//匿名内部类实现方式
// Comparator<String> comp = new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length() - s2.length();
// }
// };
// return comp;
// return new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length() - s2.length();
// }
// };
//Lambda表达式
// return (String s1,String s2) -> {
// return s1.length() - s2.length();
// };
return (s1,s2) -> s1.length() - s2.length();
}
}
- 方法的返回值是一个函数式接口,使用Lambda表达式作为结果返回
private static Comparator<String> getComparator(){
return (s1,s2) -> s1.length() - s2.length();
}
三、Supplier接口
Supplier:包含一个无参的方法
- T get():获得结果
- 该方法不需要参数,会按照某种实现逻辑(由Lambda表达式实现)返回一个数据
- Supplier<T>接口也被称为生产型接口,如果指定了接口的泛型是什么类型,接口中的get方法就会产生什么类型的数据
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
// String s = getString(() -> {
// return "火影";
// });
String s = getString(() -> "火影");
System.out.println(s);
Integer i = getInteger(() -> 20);
System.out.println(i);
}
//定义一个方法,返回一个字符串数据
private static String getString(Supplier<String> sup){
return sup.get();
}
//定义一个方法,返回一个整数数据
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
}
输出如下所示:
火影
20
四、Supplier接口获取数组最大值
import java.util.function.Supplier;
public class SupplierGetMax {
public static void main(String[] args) {
int[] arr = {19,32,52,31,25};
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);
}
private static int getMax(Supplier<Integer> sup){
return sup.get();
}
}
五、Consumer接口
Consumer<T>:包含两个方法
- void accept(T t):包含两个方法
- default Consumer<T> andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
- Consumer<T>接口也被称为消费型接口,消费的数据的数据类型由泛型指定
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
operatorString1("火影",s -> {
System.out.println(new StringBuilder(s).reverse().toString());
});
operatorString2("火影",s -> System.out.println(s),
s -> System.out.println(new StringBuilder(s).reverse().toString()));
}
private static void operatorString2(String name,Consumer<String> con1,Consumer<String> con2){
con1.andThen(con2).accept(name);
}
//定义一个方法,消费一个字符串数据
private static void operatorString1(String name, Consumer<String> con){
con.accept(name);
}
}
六、Consumer接口案例
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
String[] strArray = {"火影,10","海贼王,23"};
printInfo(strArray,(String str) ->{
String name = str.split(",")[0];
System.out.print("动画名称:" + name);
},(String str) -> {
int year = Integer.parseInt(str.split(",")[1]);
System.out.println(",更新时长:" +year);
});
}
private static void printInfo(String[] strArray,Consumer<String> con1,Consumer<String> con2){
for(String str: strArray){
con1.andThen(con2).accept(str);
}
}
}
输出如下所示:
动画名称:火影,更新时长:10
动画名称:海贼王,更新时长:23
七、Predicate接口
Predicate<T>:常用的四个方法
• boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
• default Predicate<T> negate():返回一个逻辑的否定,对应逻辑非
• default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与
• default Predicate<T> or(Predicate other):返回一个组合判断,对应短路或
• Predicate<T>接口通常用于判断参数是否满足指定的条件
import java.util.function.Predicate;
public class PredictDemo {
public static void main(String[] args) {
boolean b = checkString("hello", s -> s.length() > 8);
System.out.println(b);
boolean b1 = checkString2("hello123456", s -> s.length() > 8, s -> s.length() < 10);
System.out.println(b1);
}
//判断给定的字符串是否满足要求
private static boolean checkString(String s, Predicate<String> pre){
// return pre.test(s);
return pre.negate().test(s);
}
//同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
private static boolean checkString2(String s,Predicate<String> pre1,Predicate<String> pre2){
// return pre1.and(pre2).test(s);
return pre1.or(pre2).test(s);
}
}
八、Predicate接口案例
- String[] strArray = {"海贼王,23“,“火影,12”,“犬夜叉,2”,“棒球英豪,6”}
- 字符数组有多条动漫信息,通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,并遍历ArrayList集合
- 满足要求:动漫名称大于2,更新时长小于15年大于2年的
import java.util.ArrayList;
import java.util.function.Predicate;
public class PredictDemo {
public static void main(String[] args) {
boolean b = checkString("hello", s -> s.length() > 8);
System.out.println(b);
boolean b1 = checkString2("hello123456", s -> s.length() > 8, s -> s.length() < 10);
System.out.println(b1);
String[] strArray = {"海贼王,23","火影,12","犬夜叉,4","棒球英豪,6"};
ArrayList<String> filter = filter(strArray, s -> s.split(",")[0].length() > 2,
s -> Integer.parseInt(s.split(",")[1]) > 2 && Integer.parseInt(s.split(",")[1]) < 15);
for(String s:filter){
System.out.println(s);
}
}
//判断给定的字符串是否满足要求
private static boolean checkString(String s, Predicate<String> pre){
// return pre.test(s);
return pre.negate().test(s);
}
//同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
private static boolean checkString2(String s,Predicate<String> pre1,Predicate<String> pre2){
// return pre1.and(pre2).test(s);
return pre1.or(pre2).test(s);
}
private static ArrayList<String> filter(String[] strArray,Predicate<String> pre1,
Predicate<String> pre2){
ArrayList<String> array = new ArrayList<String>();
for(String str : strArray){
if(pre1.and(pre2).test(str)){
array.add(str);
}
}
return array;
}
}
输出如下所示:
犬夜叉,4
棒球英豪,6
九、Function接口
Function<T,R>:常用的两个方法
- R apply(T t):将此函数应用于给定的参数
- default <V> Function andThen(Function after):返回一个组合函数,首先将函数应用于输入,然后将after函数应用于结果
- Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
import java.util.function.Function;
public class FunctionDemo {
public static void main(String[] args) {
convert1("100",s -> Integer.parseInt(s));
convert2(100,i -> String.valueOf(i + 280));
convert3("100", s -> Integer.parseInt(s),i -> String.valueOf(i + 188));
}
//定义一个方法,把一个字符串转换int类型,在控制台输出
private static void convert1(String s, Function<String,Integer> fun){
Integer i = fun.apply(s);
System.out.println(i);
}
//定义一个方法,把一个int类型宕数据加上一个整数之后,转为字符串在控制台输出
private static void convert2(Integer i,Function<Integer,String> fun){
String s = fun.apply(i);
System.out.println(s);
}
//定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数之后,转为字符串在控制台输出
private static void convert3(String s,Function<String,Integer> fun1,
Function<Integer,String> fun2){
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}
}
输出如下所示:
100
380
288
十、Function接口案例
- String s = “海贼王,23”
- 请按照指定的要求进行操作:
- 通过Function接口来实现函数拼接
import java.util.function.Function;
public class FunctionDemo {
public static void main(String[] args) {
String s = "海贼王,23";
// convert(s,(String ss) -> {return s.split(",")[1];},
// (String ss) -> {return Integer.parseInt(ss);},(Integer i) -> {return i + 10;});
// convert(s,ss -> ss.split(",")[1],ss -> Integer.parseInt(ss),i -> i +10);
convert(s,ss -> ss.split(",")[1],Integer::parseInt,i -> i +10);
}
private static void convert(String s,Function<String,String> fun1,
Function<String,Integer> fun2,Function<Integer,Integer> fun3){
Integer i = fun1.andThen(fun2).andThen(fun3).apply(s);
System.out.println(i);
}
}