1、函数式接口概述
- 函数式接口: 有且仅有一个抽象方法的接口。
- Java中的函数式编程体现就是Lambda表达式。
- 所以函数式接口即可以适用于Lambda使用的接口。
如何检测一个接口是不是函数式接口?
@FunctionalInterface - 放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败。
package com.test8;
@FunctionalInterface
public interface Inter {
void show();
}
package com.test8;
public class Demo {
public static void main(String[] args) {
Inter i=()-> System.out.println("Hello world!");
i.show();
}
}
注意:自定义函数式接口时,@FunctionalInterface是可选的,就算不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。
2、函数式接口做为方法的参数
如果方法的参数是一个函数式接口,可以使用Lambda表达式作为参数传递。
package com.test9;
public class Demo {
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()+"线程启动"));
}
private static void startThread(Runnable r){
Thread t=new Thread(r);
t.start();
}
}
3、函数式接口作为方法的返回值
如果方法的返回值是一个函数式接口,可以使用Lambda表达式作为结果返回。
package com.test10;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Demo {
public static void main(String[] args) {
ArrayList<String> array=new ArrayList<String>();
array.add("aa");
array.add("b");
array.add("cccc");
array.add("ddd");
System.out.println("排序前:"+array);
Collections.sort(array);
System.out.println("自然排序后:"+array);
Collections.sort(array,getComparator());
System.out.println("指定比较器排序后:"+array);
}
private static Comparator<String> getComparator(){
return (s1,s2)->s1.length()-s2.length();
}
}
3、常用的函数式接口
Java8在java.util.function包下预定义了大量的函数数式接口供我们使用。
- Supplier接口
- Consumer接口
- Predicate接口
- Function接口
3.1、Supplier接口
Supplier:包含一个无参的方法
- T get():获得结果
- 该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据。
- Supplier接口也称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用。
案例一:
package com.test11;
import java.util.function.Supplier;
public class Demo {
public static void main(String[] args) {
String s=getString(()->"唐青枫");
System.out.println(s);
Integer i=getInteger(()->10);
System.out.println(i);
}
private static String getString(Supplier<String> sup){
return sup.get();
}
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
}
案例二:
package com.test10;
import java.util.function.Supplier;
public class Test {
public static void main(String[] args) {
int[] arr={1,9,2,7,5};
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();
}
}
3.2、Consumer接口
Consumer:包含两个方法
- void accept(T t):对给定的参数执行此操作。
- default Consumer andThen(Consumer after):返回一个组合的Consumer,依次执行操作,然后执行after操作。
- Consumer接口也称为消费型接口,它消费的数据的数据类型由泛型指定。
案例一:
package com.test10;
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
operatorString("唐青枫",(String name)->{
System.out.println(name);
});
operatorString("唐青枫",name-> System.out.println(name));
operatorString("唐青枫", System.out::println);
operatorString("唐青枫",(String name)->{
String s=new StringBuilder(name).reverse().toString();
System.out.println(s);
});
System.out.println("****************************");
operatorString("曲无忆",name-> System.out.println(name),name-> System.out.println(new StringBuilder(name).reverse().toString()));
}
private static void operatorString(String name, Consumer<String> con){
con.accept(name);
}
private static void operatorString(String name,Consumer<String> con1,Consumer<String> con2){
con1.andThen(con2).accept(name);
}
}
案例二:
package com.test10;
import java.util.function.Consumer;
public class ConsumerTest {
public static void main(String[] args) {
String[] arr={"唐青枫,20","曲无忆,21","离玉堂,22","叶知秋,23"};
printInfo(arr,
(String str)->{
String name=str.split(",")[0];
System.out.print("姓名:"+name);
},
(String str)->{
int age=Integer.parseInt(str.split(",")[1]);
System.out.println(",年龄:"+age);
});
}
private static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2){
for(int i=0;i<arr.length;i++){
con1.andThen(con2).accept(arr[i]);
}
}
}
3.3、Predicate接口
Predicate:常用的四个方法:
boolean test(T t) :对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值。default Predicate<T> negate() :返回一个逻辑的否定,对应逻辑非。default Predicate<T> and(Predicate other) :返回一个组合判断,对应短路与。default Predicate<T> or(Predicate other) :返回一个组合判断,对应短路或。- Predicate接口通常用于判断参数是否满足指定的条件。
negate、test案例
package com.test12;
import java.util.function.Predicate;
public class Demo {
public static void main(String[] args) {
boolean b=checkString("Hello",str->str.length()>8);
System.out.println(b);
System.out.println("****************************");
b=checkString1("Hello",str->str.length()>8);
System.out.println(b);
}
private static boolean checkString(String str, Predicate<String> pre){
return pre.test(str);
}
private static boolean checkString1(String str,Predicate<String> pre){
return pre.negate().test(str);
}
}
and、or案例
package com.test12;
import java.util.function.Predicate;
public class Demo1 {
public static void main(String[] args) {
boolean b1=checkString("hello",s->s.length()>8,s->s.length()<15);
boolean b2=checkString("helloworld",s->s.length()>8,s->s.length()<15);
System.out.println(b1);
System.out.println(b2);
}
private static boolean checkString(String str, Predicate<String> pre1, Predicate<String> pre2){
return pre1.and(pre2).test(str);
}
}
案例:筛选满足条件的数据 姓名长度>2且年龄>20
package com.test13;
import java.util.ArrayList;
import java.util.function.Predicate;
public class Demo {
public static void main(String[] args) {
String[] arr={"唐青枫,20","慕晴,21","曲无忆,22","孔雀,23","离玉堂,25"};
ArrayList<String> arrayList=myFilter(arr,str->str.split(",")[0].length()>2,
str->Integer.parseInt(str.split(",")[1])>20);
for(String str:arrayList){
System.out.println(str);
}
}
private static ArrayList<String> myFilter(String[] arr, Predicate<String> pre1, Predicate<String> pre2){
ArrayList<String> arrayList=new ArrayList<String>();
for(int i=0;i<arr.length;i++){
if(pre1.and(pre2).test(arr[i])){
arrayList.add(arr[i]);
}
}
return arrayList;
}
}
3.4、Function接口
Function<T,R> :常用的两个方法
R apply(T t) :将此函数应用于给定的参数。default<V> Function andThen(Function after) :返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果。Function<T,R> :接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值。
package com.test14;
import java.util.function.Function;
public class Demo {
public static void main(String[] args) {
convert("666",(s)->Integer.parseInt(s));
convert(666,i->String.valueOf(i));
convert("666",s->Integer.parseInt(s),i->String.valueOf(i));
}
private static void convert(String s, Function<String,Integer> fun){
int i=fun.apply(s);
System.out.println(i);
}
private static void convert(Integer i,Function<Integer,String> fun){
String s=fun.apply(i);
System.out.println(s);
}
private static void convert(String s,Function<String,Integer> fun1,Function<Integer,String> fun2){
String str=fun1.andThen(fun2).apply(s);
System.out.println(str);
}
}
|