函数式接口
约 2017 字大约 7 分钟
2026-04-04
函数式接口
有且只有一个公开抽象方法的接口 还包括默认方法,静态和私有的
即适用于函数式编程场景的接口。函数式编程的体现:lambda表达式
所以函数式接口就是可以适用于lambda表达式的接口,java中的lambda才可以顺利的进行推导
语法糖
是指使用更方便,但原理不变的代码语法 比如:遍历集合时使用的增强for循环
函数式接口对应注解
@FunctionalInterface
可以检查该接口是否是函数式接口函数式接口使用方式
一般可以用方法的参数作为返回值
@FunctionalInterface
public interface MyInterface {
public void come();
}
public static void main(String[] args) {
show(new MyInterface() {
@Override
public void come() {
System.out.println("调用函数式接口");
}
});
// lambda
show(()->{
System.out.println("调用函数式接口");
});
//{}省略
show(()->System.out.println("调用函数式接口"));
}
public static void show(MyInterface myInterface){
myInterface.come();
}拼接字符串操作
发现代码性能浪费的问题
调用showlog方法时,传递第二个参数是一个拼接的字符的串
运行时会先进行字符的拼接, 然后调用showLog方法
如果该方法传递的参数不是1的时候,那么就会发现拼接的字符没有用到
白白浪费性能
public static void main(String[] args) {
String msg1 = "hello";
String msg2 = "world";
String msg3 = "hahah";
//调用日志方法,传递参数
showLog(1, msg1 + msg2 + msg3);
}
// 拼接日志信息
public static void showLog(int level, String msg) {
if (level == 1) {
System.out.println(msg);
}
}使用lambda表达式作为参数传递的时候,仅仅是把参数传递到showLog方法中
只有满足Level为1时
才会调用接CMyBuilder接口中buiIderMsg方法
才会有字符拼接的功能
如果条件不满足时
那么接口MyBuilder接口中builderMsg方法不会执行
不会有字符串的拼接
所以性能不会浪费
public static void main(String[] args) {
String msg1 = "hello";
String msg2 = "world";
String msg3 = "hahah";
showLog(1, () -> {
System.out.println("如果方法满足就执行");
return msg1 + msg2 + msg3;
});
showLog(2, () -> {
System.out.println("如果方法不满足就不执行");
return msg1 + msg2 + msg3;
});
}
private static void showLog(int level, MyInterface myInterface) {
if (level == 1) {
myInterface.builderMsg();
}
}
使用Lambda进行性能的优化
Lambda的特点:延时加载 Lambda的使用前提:必须要使用函数式接口
Runnable接口使用Lambda表达式
列如Runnable接口就是一-个函数式接口
假设有一个方法使用该接口作为参数,那么我们就可以使用Lambda进行参数传递
这种情况其实和Thread类的构造方法参数为Runnable没有本质的区别
public static void main(String[] args) {
startThread(new Runnable() {
@Override
public void run() {
System.out.println("使用匿名内部类调用线程");
}
});
startThread(()->{
System.out.println("使用Lambda表达式调用线程");
});
}
public static void startThread(Runnable runnable){
new Thread(runnable).start();
}字符串数组比较
public static void main(String[] args) {
String[] str={"dq2f","话费","dwegrw","hf90wu"};
Arrays.sort(str,getComparator());
System.out.println(Arrays.toString(str));
}
private static Comparator<String> getComparator(){
// (1)
return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
};
// (2)
return (String o1,String o2)->{
return o1.length()-o2.length();
};
// (3)
return (o1,o2)-> o1.length()-o2.length();
// (4)
return Comparator.comparingInt(String::length);
}常用函数式接口
java.util.Function
Supplier
@FunctionalInterfacepublic interface Supplier<T> 称为生产型接口 ,指定接口的类型 指定接口的泛型是什么类型,该接口中的方法就能返回什么类型的数据
抽象方法get
T get() 用来获取一个泛型的参数指定类型的对象数据
public static void main(String[] args) {
getStr(() -> "hello" + "world");
}
public static String getStr(Supplier<String> stringSupplier) {
return stringSupplier.get();
}求数组最大值
public static void main(String[] args) {
int[] arr = {34, 6, 78};
getArrMax(() -> {
int max = arr[0];
for (int i : arr) {
if (i > max) {
max = i;
}
}
return max;
});
}
private static Integer getArrMax(Supplier<Integer> supplier) {
return supplier.get();
}Consumer
@FunctionalInterfacepublic interface Consumer<T>消费者接口 ,泛型是什么类型,就可以使用accept方法消费什么类型的数据 至于怎么使用定义,可以计算,输出
抽象方法accept
void accept(T t) 对给定的参数执行此操作。
反转字符串
public static void main(String[] args) {
method("abcd",(name)->{
String str=new StringBuilder(name).reverse().toString();
System.out.println(str);
});
}
public static void method(String name, Consumer<String> consumer){
consumer.accept(name);
}默认方法andThen
default Consumer<T> andThen(Consumer<? super T> after)
需要两个Consumer接口,可以把Consumer接口组合到一起,对数据进行消费

public static void main(String[] args) {
// 让给定的字符串可以大写也可以小写
String str="Hello";
show(str,
(name)-> System.out.println(name.toUpperCase()),
(name)-> System.out.println(name.toLowerCase()));
}
public static void show(String name, Consumer<String> con1,Consumer<String> con2){
con1.andThen(con2).accept(name);
}package com.fac.demo5;
import java.util.function.Consumer;
/**
* @Description TODO
* @Classname Cousumer3
* @Date 2021/8/19 11:46
* @Created by 折腾的小飞
*/
public class Cousumer3 {
public static void main(String[] args) {
// String[] peoplename = {"张三", "男", "李四", "女"};
String[] peoplename = {"张三,男", "李四,女"};
show(peoplename,
(name)->{
// System.out.println("姓名:"+name);
System.out.println("姓名:"+name.split(",")[0]);
},
(gender)->{
// System.out.println("性别:"+gender);
System.out.println("性别:"+gender.split(",")[1]);
});
}
private static void show(String[] str, Consumer<String> con1,Consumer<String> con2){
for (String s : str) {
con1.andThen(con2).accept(s);
}
for (int i = 0; i < str.length; i++) {
if (i%2==0){
con1.accept(str[i]);
}else{
con2.accept(str[i]);
}
}
}
}
Predicate
@FunctionalInterfacepublic interface Predicate<T> 作用:对某种数据类型的数据进行一个判断,结果返回boolean
抽象方法test
boolean test(T t)用来对指定数据类型数据的判断 结果:符合条件就是true,不符合就是false
public static void main(String[] args) {
String str="bdfuiegb从吃完饭";
boolean b = checkLength(str, (s) ->
s.length() > 10
);
System.out.println(b);
}
public static boolean checkLength(String s, Predicate<String> predicate){
return predicate.test(s);
}默认方法
逻辑表达式:可以连接多个判断条件 相当于逻辑运算关系: &&:default Predicate<T> and(Predicate<? super T> other)||:default Predicate<T> or(Predicate<? super T> other)!:default Predicate<T> negate()
静态方法
==:static <T> Predicate<T> isEqual(Object targetRef)
// 判断大于10且包含k
public static void main(String[] args) {
String str = "g8dgf";
checkString(
s -> s.length() > 10,
s -> s.contains("k"),
str);
}
public static boolean checkString(Predicate<String> pr1, Predicate<String> pr2, String str) {
return pr1.and(pr2).test(str); // pr1.test(str)&&pr2.test(str)
}//// 判断大于10或者包含k
public static void main(String[] args) {
String str = "hoifho";
boolean b = isAccord(s -> s.length() > 10,
s -> s.contains("k"), str);
System.out.println(b);
}
private static boolean isAccord(Predicate<String> pre1, Predicate<String> pre2, String s) {
return pre1.or(pre2).test(s);
}//筛选女生且名字等于4个字
public static void main(String[] args) {
String[] strName = {"欧阳拉拉,女", "杨洋,男", "司樊登,男", "迪丽热巴,女", "杨幂,女"};
HashSet<String> set=check(
strName,
s->s.split(",")[1].equals("女"),
s->s.split(",")[0].length()>=4
);
System.out.println(set);
}
private static HashSet<String> check(String[] s, Predicate<String> pre1, Predicate<String> pre2) {
HashSet<String> set=new HashSet<>();
for (String s1 : s) {
if(pre1.and(pre2).test(s1)){
set.add(s1);
}
}
return set;
}Function
@FunctionalInterface]public interface Function<T,R> 用来根据一个类型的数据得到另一个类型的数据 前者称为前置条件,后者称为后置条件
抽象方法apply
R apply(T t) 根据类型T的参数获取类型R的结果 使用场景:String类型的数据转换为Integer类型
默认方法
default <V> Function<T,V> andThen(Function<? super R,? extends V> after) 相当于进行两次转换
public static void main(String[] args) {
String str = "30";
IntConversionStr(str,s -> Integer.valueOf(s)+50,s->String.valueOf(s));
}
public static void IntConversionStr(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
// Integer applyInt = fun1.apply(s);
// System.out.println(applyInt);
// String applyStr = fun2.apply(applyInt);
// System.out.println(applyStr);
String apply = fun1.andThen(fun2).apply(s);
System.out.println(apply);
}方法引用
package com.fac.Work8_19.Test11;
/**
* @Description TODO
* @Classname Student
* @Date 2021/8/19 21:19
* @Created by 折腾的小飞
*/
public class Student {
private String name;
private int score;
public Student() {
}
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
public static void main(String[] args) {
ArrayList<Student> list=new ArrayList();
Collections.addAll(
list,
new Student("谢霆锋",85),
new Student("章子怡",63),
new Student("刘亦菲",77),
new Student("黄晓明",33),
new Student("岑小村",92)
);
// 从小到大,升序 匿名内部类
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student student, Student t1) {
return student.getScore()-t1.getScore();
}
});
System.out.println(list);
// 从大到小,降序 Lambda表达式
Collections.sort(list,(o1,o2)->{
return o2.getScore()-o1.getScore();
});
System.out.println(list);
// 方法引用
Collections.sort(list,Comparator.comparingInt(Student::getScore)); // 升序
System.out.println(list);
Collections.sort(list,Comparator.comparingInt(Student::getScore).reversed()); // 降序
System.out.println(list);
}贡献者
更新日志
fb8bc-更新为vuepress于