1.1 概述
如果说一个接口内有且只有一个方法,而且该方法是一个缺省属性为public abstract方法,该接口可以称之为是一个函数式接口。
其中分为自定义函数式接口,还有系统中提供的函数式接口
Comparator<T> Runnable
可以直接理解JDK1.8的新特征,Lambda表达式来使用。
Lambda表达式对比匿名内部类使用
1. 简化了代码结构
2. 节约了内存资源
3. 让程序员更加关注,我要做什么,而不是为了做什么需要完成什么
1.2 @FunctionalInterface 使用
- 类似于
@Override
开启代码重写格式严格检查
/**
* 使用@FunctionalInterface检查函数式接口格式问题
* 要求当前接口中有且只有一个缺省属性为public abstract的方法
*
* @author Anonymous 2020/3/11 9:55
*/
@FunctionalInterface
public interface FunctionalType {
void test();
}
1.3 使用自定义的函数式接口作为方法的参数使用
/**
* 自定义函数式接口作为方法的参数演示
*
* @author Anonymous 2020/3/11 9:55
*/
public class Demo1 {
public static void main(String[] args) {
/*
使用匿名内部类来完成函数式接口的使用,但是这种方式有悖于函数式接口的目的
Low
useFunctionalInterface(new FunctionalType() {
@Override
public void test() {
System.out.println("匿名内部类的匿名对象直接作为方法的参数。");
}
});
int(*) (char **, int *)
C语言中的函数指针
如果是C语言中,这需要的参数是方法名
*/
useFunctionalInterface(() -> System.out.println("函数式接口 lambda表达式实现完成方法,实现目的"));
}
/**
* 使用一个函数式接口作为方法的参数
*
* @param ft 函数式接口的实现类对象,或者说直接操作本质,直接传入Lambda表达式
*/
public static void useFunctionalInterface(FunctionalType ft) {
ft.test();
}
}
- 代码中使用函数式接口
- 让程序的目的性更强
- 提供复用,普适性的价值
- 节约资源
2. 函数式编程思想
2.1 Lambda延迟执行
2.1.1 日志记录
- 日志是否保存会存在等级限制
演示一个根据不同的等级来记录log日志
要求:
等级 == 1 记录log日志,其他情况不记录
enum Level {
/**
* 枚举测试
*/
HIGH, MIDDLE, LOWER
}
/**
* 日志等级记录操作
*
* @author Anonymous 2020/3/11 10:17
*/
public class Demo1 {
public static void main(String[] args) {
/*
这里存问题:
"异常位置XXX," + "异常问题XXX," + "异常时间XXX" 字符叠加过程,会产生
5个字符串
这5个字符串如果Level.HIGH等级是有用的,但是除此之外是没有任何作用的。
MIDDLE,LOWER是没有必要进行字符串累加,存在资源浪费问题。
字符串的累加过程,需要经过Level判断之后才可以执行,避免没有必要的性能浪
费。
这里就可以使用Lambda表达式执行的延迟性,在没有满足level情况下,不去做字
符串累加过程。
这里需要【函数式接口】
*/
log(Level.MIDDLE, "异常位置XXX," + "异常问题XXX," + "异常时间XXX");
}
/**
* 判断等级是否需要记录当前日志信息
*
* @param level 等级,枚举类型
* @param logMsg 需要记录的日志信息
*/
public static void log(Level level, String logMsg) {
// 判断是否满足枚举类型 Level.HIGH要求
if (Level.HIGH == level) {
System.err.println(logMsg);
}
}
}
2.1.2 使用函数式接口提供日志信息功能
- 这里需要一个函数式接口,返回值类型是String类型,其他的无所谓。
/**
* 提供返回值为String类型方法的函数式接口
*
* @author Anonymous 2020/3/11 10:52
*/
@FunctionalInterface
public interface LogMessage {
/**
* 函数式接口中方法内容,该方法的返回值是String类型
*
* @return String类型返回值
*/
String returnLogMessage();
}
/**
* 使用函数式接口完成Log日志记录问题
*
* @author Anonymous 2020/3/11 10:53
*/
public class Demo2 {
public static void main(String[] args) {
String msg1 = "异常位置XXX,";
String msg2 = "异常问题XXX,";
String msg3 = "异常时间XXX";
log(Level.LOWER, () -> {
System.out.println("Lambda表达式执行!!!");
return msg1 + msg2 + msg3;
});
}
/**
* 根据日志等级Level来确定是否需要记录日志
*
* @param level Level枚举类型,有三个数据 HIGH MIDDLE LOWER
* @param lm LogMessage函数式接口做方法的参数
*/
public static void log(Level level, LogMessage lm) {
/*
发现当Level等级为HIGH,执行对应的lm.returnLogMessage();
Level等级不是HIGH不执行对应的方法。
Lambda执行延迟问题不是Lambda效率执行慢,而是在执行之前多了一个判断
是在判断之后才可以执行对应的代码。
不执行代码字符串不会产生拼接导致的资源浪费问题,从而提高效率。
*/
if (Level.HIGH == level) {
// 通过函数式接口获取调用对应的returnLogMessage()方法
System.err.println(lm.returnLogMessage());
}
}
public static void testEnum(int level) {
if (Level.HIGH.getStatus() == level) {
}
}
}
2.2 Lambda作为方法参数和返回值
- 参数演示:
Runnable接口
/**
* Runnable接口函数式接口使用,作为方法的参数
*
* @author Anonymous 2020/3/11 11:18
*/
public class Demo3 {
public static void main(String[] args) {
// 匿名内部类来完成对应当前Runnable接口实现类对象使用,作为Thread构造方法参数
// low
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程代码");
}
}).start();
// Lambda表达式直接作为方法的参数
Thread thread = new Thread(() -> {
System.out.println("线程执行需要时间");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程执行");
}
, "线程");
thread.start();
}
}
-
Java中提供的比较接口Comparator
利用一些返回值作为方法中操作的调节 -
public interface Comparator {
int compare(T o1, T o2);
}
import java.util.Arrays;
import java.util.Comparator;
/**
* Lambda表示完成函数式接口,利用返回值作为其他操作所需的数据
*
* @author Anonymous 2020/3/11 11:25
*/
public class Demo4 {
public static void main(String[] args) {
/*
字符串排序默认是一个字典顺序
*/
String[] arr = {"eeeeeeee", "2a","dddd", "1bb", "ccccccc", "3fffff"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
System.out.println("-----------------------------------------");
// 利用一个函数式接口完成的方法,利用方法的返回值作为当前sort方法运行
// 所需参数,该参数用于比较规则约束
Arrays.sort(arr, stringComparator());
System.out.println(Arrays.toString(arr));
System.out.println("-----------------------------------------");
Arrays.sort(arr, (a, b) -> a.length() - b.length());
Arrays.sort(arr, Comparator.comparingInt(String::length));
/*
Comparator.comparingInt(String::length)
Comparator:接口
comparingInt:按照Int类型方式比较判断
String:表示比较的类型是String,比较什么类型用什么类型
length:按照String类型的哪一种方式比较
*/
System.out.println(Arrays.toString(arr));
}
/**
* 按照字符串长度排序,返回值类型是一个Comparator<String>接口
* 这里需要完成Comparator接口中的compare方法
*
* @return 已经完成方法体的Comparator接口,并且数据类型是String类型
*/
public static Comparator<String> stringComparator() {
/*
public interface Comparator<T> {
int compare(T o1, T o2);
}
*/
return (a, b) -> b.length() - a.length();
}
}