函数式接口-Java

第一章 函数式接口

1.1 概念

  • 函数式接口在Java中指有且仅有一个抽象方法的接口,接口中可以包含其他的方法(私有,默认,静态)体现方式是Lambda

1.2 格式

1
2
3
4
@FunctionalInterface
修饰符 interface 接口名称{
public abstract 返回值类型 方法名称(参数);
}

1.3 @FunctionalInterface

  • 注解,检测接口是否是一个函数式接口

第二章 函数式编程

2.1 Lambda的延迟执行

日志案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class logger {
//定义一个根据日志的级别,显示日志的方法
public static void showLog(int level,String message){
if(level == 1){
System.out.println(message);
}
}

public static void main(String[] args) {
//定义三个日志信息
String msg1 = "hello";
String msg2 = "hxx";
String msg3 = "qzy";
//调用showLog
showLog(1,msg1+msg2+msg3);
showLog(2,msg1+msg2+msg3);//不会打印,字符串拼接操作浪费
}
}

日志案例优化

  • 使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中,只有满足条件,才会调用MessageBuilder中的方法builderMessage进行字符串的拼接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@FunctionalInterface
public interface MessageBuilder {
public abstract String builderMessage();
}
public class logger {
public static void showLog(int level,MessageBuilder mb){
if(level == 1){
System.out.println(mb.builderMessage());
}
}
public static void main(String[] args) {
//定义三个日志信息
String msg1 = "hello";
String msg2 = "hxx";
String msg3 = "qzy";
showLog(1,()->{
return msg1+msg2+msg3;
});
}
}

函数式接口作为方法的返回值

  • 如果一个方法的返回值类型是一个函数式接口,那么可以直接返回一个Lambda表达式。当需要通过一个方法来获取一个java.util.Comparator接口类型的对象作为排序算法时,就可调该方法获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static Comparator<String> getComparable(){
/*return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.length()-o1.length();
}
};*/
/*return (o1,o2)->{
return o2.length()-o1.length();
};*/
return (o1,o2)->o2.length()-o1.length();

}
public static void main(String[] args) {
String[] str = {"aa","b","dssd"};
Arrays.sort(str,getComparable());
System.out.println(Arrays.toString(str));
}

第三章 常用函数式接口

3.1 Supplier接口

  • java.util.function.Supplier< T >接口仅包含一个无参的方法:T get()。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,所以Lambda表达式需要对外提供一个符合泛型类型的对象数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    //定义一个方法,参数传递Supplier接口
public static String getString(Supplier<String> sup) {
return sup.get();
}
public static int getMax(Supplier<Integer>sup){
return sup.get();
}
public static void main(String[] args) {
String s = getString(() -> {
return "hxx";
});
System.out.println(s);
int[] arr = {10,20,50};
int maxVaule = getMax(()->{
int max = arr[0];
for (int i : arr) {
if(i>max) max = i;
}
return max;
});
System.out.println(maxVaule);
}

3.2 Consumer接口

抽象方法:accept

Consumer 接口中包含抽象方法void accept(T t)消费一个指定泛型的数据

1
2
3
4
5
6
7
8
9
10
public static void method(String name, Consumer<String> cos){
cos.accept(name);
}
public static void main(String[] args) {
method("hxx",(String name)->{
System.out.println(name);
String rName = new StringBuffer(name).reverse().toString();
System.out.println(rName);
});
}

默认方法andThen

  • 需要两个Consumer接口,可以把两个Consumer接口连接起来
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void method1(String name,Consumer<String> con1,Consumer<String>con2){
con1.accept(name);
con2.accept(name);
//使用andThen方法
con1.andThen(con2).accept(name);
}
public static void main(String[] args) {
String str = "hxx";
//判断字符串是否长度大于5
checkString(str,(s)->{
return s.length()<5;
});
method1("hxx",
(name)-> System.out.println(name.toUpperCase()),
(name)-> System.out.println(name));
}

3.3 Predicate接口

  • 当需要对某种类型的数据进行判断,可以使用 java.util.function.Predicate<T>接口

抽象方法:boolean test(T t)用于条件判断

1
2
3
4
5
6
7
8
9
10
11
public static boolean checkString(String str, Predicate<String> pre){
return pre.test(str);
}

public static void main(String[] args) {
String str = "hxx";
//判断字符串是否长度大于5
checkString(str,(s)->{
return s.length()<5;
});
}

默认方法:and、or、negate

  • 将两个Predicate条件使用逻辑连接起来实现与或非效果时,可以使用default方法and
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static boolean checkString1(String str, Predicate<String> pre1, Predicate<String> pre2){
//return pre1.test(str) && pre2.test(str);
//return pre1.and(pre2).test(str);
return pre1.or(pre2).test(str);
//return pre1.negate().test(str);
}
public static void main(String[] args) {
String str = "hxxqzy";
//判断字符串是否长度大于5
boolean b=checkString1(str,
(s)->{ return s.length()<5; },
(s)->{ return s.contains("qzy");}
);
}

3.4 Function接口

  • java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据

抽象方法:apply

  • R apply(T t)根据类型T的参数获取类型R的结果。如将String转换为Integer类型
1
2
3
4
5
6
7
8
9
10
11
public static void change(String str, Function<String,Integer> fun){
Integer in = fun.apply(str);
System.out.println(in);
}
public static void main(String[] args) {

String str = "1234";
change(str,(String s)->{
return Integer.parseInt(s);
});
}

andThen方法:组合操作

  • 将String类型的”123“转换为Integer类型,加10之后转换为String类型
1
2
3
4
5
6
7
8
9
10
11
12
public static void change(String str, Function<String,Integer> fun1,Function<Integer,String> fun2){
String ss = fun1.andThen(fun2).apply(str);
System.out.println(ss);
}

public static void main(String[] args) {
String str = "1234";
change(str,
(String s)->{ return Integer.parseInt(s)+10; },
(Integer i)->{return i+"";});

}