函数式接口, 一般可以作为方法的参数和返回值类型
- 案例1:函数式接口作为方法的参数
#自定义函数式接口
package FunctionInterface;
public interface MyFunctionInterface {
public abstract void method();
}
public class functionDemo {
public static void show(MyFunctionInterface myFunctionInterface) {
myFunctionInterface.method();
}
public static void main(String[] args) {
// 方式1
// 调用show方法,参数是一个接口,可以传递接口的匿名内部类
show(new MyFunctionInterface(){
@Override
public void method() {
System.out.println("使用匿名内部类重写抽象方法");
}
});
// 方式2
// Lambda表达式
show(() ->{
System.out.println("Lambda表达式实现");
});
}
- 函数式接口作为参数
public class functionDemo {
public static void threadStart(Runnable run) {
new Thread(run).start();
}
// 方式1:匿名内部类
threadStart(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "启动了");
}
});
// 注意:参数Runnabl 一个函数式接口,并且只有一个抽象方法(run),可以传递Lambda表达式
//方式2: Lambda表达式
threadStart(() -> System.out.println(Thread.currentThread().getName() + "启动了"));
}
输出:
Thread-0启动了
Thread-1启动了
- 案例2:函数式接口作为返回值
# 对字符串按照字符长度倒序
package FunctionInterface;
import java.util.Arrays;
import java.util.Comparator;
public class LambdaReturn {
public static Comparator<String> getComparator(){
//方式1:方法的返回值类型是一个接口,我们可以返回这个接口的匿名内部类
/*
return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// 按照字符串的降序排列
return o2.length() - o1.length();
}
};
*/
// 方式1: Lambda表达式
return (String o1, String o2) -> {
// 按照字符串的降序排列
return o2.length() - o1.length();
};
// Lambda优化
// return (o1, o2) -> o2.length() - o1.length();
}
public static void main(String[] args) {
// 函数式接口作为返回值
String[] strList = {"abc", "bcd", "wudy", "petwr", "world"};
System.out.println("排序前=" + Arrays.toString(strList));
Arrays.sort(strList, getComparator());
System.out.println("排序后=" + Arrays.toString(strList));
}
}
输出:
排序前=[abc, bcd, wudy, petwr, world]
排序后=[petwr, world, wudy, abc, bcd]
- 案例3: Lambda延迟执行
- 有些场景的代码执行后,结果一定会被使用,从而造成性能浪费,而Lambda是延迟执行的,正好可以作为解决方案
性能浪费的日志案例:对日志消息进行拼接后,在满足条件的情况下进行打印输出
package FunctionInterface;
public class LambdaDelay {
public static void main(String[] args) {
String msg1 = "hello";
String msg2 = "world";
String msg3 = "java";
showLog(2, msg1 + msg2 + msg3);
}
public static void showLog(int level, String msg) {
if (level == 1) {
System.out.println("日志级别等于1" + msg);
}
}
注意: 上述代码存在的问题: 拼接的字符串在level != 1 的时候并没有用到,存在性能浪费
- 优化如下:
- 使用Lambda优化日志案例
特点:延时加载, 定义一个显式日志的方法,方法的参数传递日志的等级和MessageBuilder接口
使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中
只有满足条件(日志等级是1),才会调用接口MessageBuilder中的方法messageBuilder
如果不满足条件,日志的等级不是1,那么接口MessageBuilder中的方法messageBuilder不会执行
所以拼接字符串的代码也不会执行所以不会存在性能的浪费
package FunctionInterface;
@FunctionalInterface
public interface MessageBuilder {
// 定义一个拼接消息的抽象方法, 返回被拼接的消息
public abstract String builderMessage();
}
package FunctionInterface;
public class LambdaDelay {
public static void main(String[] args) {
String msg1 = "hello";
String msg2 = "world";
String msg3 = "java";
showLog(1, () -> {
return msg1 + msg2 + msg3;
});
}
private static void showLog2(int level, MessageBuilder messageBuilder) {
if (1 == level) {
System.out.println("测试啥时候进来这里啊!");
System.out.println(messageBuilder.builderMessage());;
}
}
结论: 当level==2的时候,不会进入Lambda表达式中,就不会执行字符串拼接,从而节省性能
- 案例4: 使用Supplier接口作为方法参数类型
Supplier 被称之为生产型接口,指定接口的范型是什么类型,那么接口中的get方法就会生产什么类型的数据
package FunctionInterface;
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
// 调用getSupplier方法, 方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
String name = getSupplier(() -> {
return "wudy";
});
//String name = getSupplier(() -> "wudy");
System.out.println(name);
}
public static String getSupplier(Supplier<String> supplier) {
return supplier.get();
}
}
输出:
wudy
- Supplier接口作为方法参数类型, 通过Lambda表达式求出int数组中的最大值
package FunctionInterface;
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
Integer[] list = {88, 10, -12, -34, 0, 65, 102};
int maxValue = getMax(() -> {
System.out.println("second");
int max = list[0];
for (int i: list) {
if (i > max) {
max = i;
}
}
return max;
});
System.out.println(maxValue);
}
public static Integer getMax(Supplier<Integer> supplier) {
System.out.println("first");
return supplier.get();
}
}
输出:
first
second
102
Consumer接口是一个消费型接口,范型指定什么类型,就可以使用accept方法消费什么类型的数据
- 案例5: Consumer反转字符串
package FunctionInterface;
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
method("wudy", (String name) -> {
// 重写accept
// 反转字符串
String revName = new StringBuffer(name).reverse().toString();
System.out.println(revName);
});
}
public static void method(String name, Consumer<String> consumer){
consumer.accept(name);
}
}
输出:
yduw
- AndThen方法: 需要两个Consumer接口,可以把两个Consumer接口组合到一起,再对数据进行消费
package FunctionInterface;
import java.util.function.Consumer;
public class ConsumerAndThen {
public static void main(String[] args) {
method("Hello World", (String name) -> {
System.out.println("执行con1=" + name.toUpperCase());
}, (String name) -> {
System.out.println("执行con2=" + name.toLowerCase());
});
}
public static void method(String s, Consumer<String> con1, Consumer<String> con2){
// 先执行con2消费数据,再执行con1消费数据
con2.andThen(con1).accept(s);
}
}
输出:
执行con2=hello world
执行con1=HELLO WORLD
- AndThen方法: 格式化打印信息
- 将下面的字符串按照格式"姓名:XX。性别:XX" 的格式打印出来,要求将打印姓名的动作作为第一个Consumer接口的Lambda实例,
将打印性别的动作作为第二个Consumer接口的Lambda实例,将两个Consumer接口按照顺序拼接到一起
package FunctionInterface;
import java.util.function.Consumer;
public class FormatPrint {
public static void main(String[] args) {
String[] strList = {"wudy,男","peter,女","timo,女"};
for (String str: strList) {
printInfo(str, (String name) -> {
name = str.split(",")[0];
System.out.print("姓名:" + name);
}, (String sex) -> {
sex = str.split(",")[1];
System.out.println("。性别:" + sex + "。");
});
}
}
public static void printInfo(String str, Consumer<String> con1, Consumer<String> con2) {
con1.andThen(con2).accept(str);
}
}
输出:
姓名:wudy。性别:男。
姓名:peter。性别:女。
姓名:timo。性别:女。
- 有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果
package FunctionInterface;
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
String str = "macBookPro";
boolean b = checkString(str, (String s) -> s.length() >15);
System.out.println(b);
}
public static boolean checkString(String str, Predicate<String> predicate) {
return predicate.test(str);
}
}
输出:
false
网友评论