目录
I. java.util.function包下的常用函数式接口
MyFunction:接收一个类型为T的参数,返回一个类型为R的结果,>
一、导言
函数式编程是一种强调函数组合和纯函数的编程范式,它基于λ演算和数学中的函数式和集合论。在Java中,函数式接口为函数式编程提供了强大的支持,它们作为Lambda表达式的目标类型,简化了代码编写并提高了可读性。函数式编程和函数式接口在Java中的引入,为我们带来了更灵活和简洁的编程方式。
二、函数式接口的定义和特点
I. 什么是函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
II. 函数式接口的特点和约束
- 单一抽象方法:函数式接口只有一个未实现的抽象方法。
- Lambda表达式目标类型:函数式接口可以作为Lambda表达式的目标类型,即Lambda表达式可以作为函数式接口的实现。
- 默认方法和静态方法:函数式接口可以包含默认方法和静态方法,但它们不影响接口的函数式特性。
- 标记注解:函数式接口可以使用@FunctionalInterface注解进行标记,该注解用于提醒编译器检查接口是否符合函数式接口的定义。
III. Lambda表达式和函数式接口的关系
- Lambda表达式可以替代使用匿名内部类的方式来实现函数式接口中的抽象方法
- Lambda表达式可以通过函数式接口来实现,即可以将Lambda表达式赋给函数式接口类型的变量或作为参数传递给接受函数式接口作为参数的方法。
Lambda表达式和函数式接口的关系可以简单总结为:Lambda表达式是实现函数式接口的一种方式。
三、Java中常用的函数式接口
I. java.util.function包下的常用函数式接口
Predicate<T>:判断传入的对象是否满足某个条件
接口声明
// 该接口的特点:有参数、有返回值、且返回值类型为boolean类型。
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
}
代码示例演示
public class PredicateFunction {
public static void main(String[] args) {
// Predicate<T> 通常用于条件的判断
// 需求: 判断姓名是否合法(姓名长度小于3合法)
predicateTest(new Predicate<String>() { // 使用匿名内部类创建对象,并实现Predicate接口
@Override
public boolean test(String s) { // 重写Predicate接口中的test方法
return s.length() > 3; //指定判定规则
}
});
}
/**
* 检查姓名长度是否超过三个字符
* @param predicate 谓词
*/
public static void predicateTest(Predicate<String> predicate) {
boolean result = predicate.test("迪丽热巴"); //调用test方法,注意此时被调用的test方法已被重写
System.out.println(result ? "名字太长了" : "名字合法");
}
}
Function<T, R>:将传入的对象映射为另一个对象
接口声明
// 该接口的特点:有参数、有返回值。
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
}
代码示例演示
public class FunctionInterface {
public static void main(String[] args) {
// Function<T, R>能够将参数由一种类型转成另一种类型,通常用于不同对象之间的映射转换
// 需求:将String类型转为Integer类型
functionTest(new Function<String, Integer>() { // 使用匿名内部类创建创建对象,并实现Function接口
@Override
public Integer apply(String s) { // 重写Function接口中的apply方法
return Integer.valueOf(s);
}
});
}
/**
* 将字符串转为数字
* @param function 函数参数
*/
public static void functionTest(Function<String,Integer> function){
Integer number = function.apply("1234"); //调用Function接口中的apply方法
System.out.println(number); // 输出结果
}
}
Consumer<T>:对传入的对象执行某个操作
接口声明
// 该接口的特点:有参数、无返回值
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
代码示例演示
public class ConsumerFunction {
public static void main(String[] args) {
// 该接口一般用于数组或集合的遍历输出
consumerTest(new Consumer<String>() { // 使用匿名内部类创建创建对象,并实现Consumer接口
@Override
public void accept(String str) {
//将字符串转为小写
System.out.println(str.toLowerCase());
//将字符串转为大写
System.out.println(str.toUpperCase(Locale.ROOT));
}
});
}
/**
* 一个字符串转成大写和小写的字符串
* @param consumer 输入的参数
*/
public static void consumerTest(Consumer<String> consumer){
String str="Hello World!";
consumer.accept(str);
}
}
Supplier<T>:生成一个对象
接口声明
// 该接口的特点:无参数、有返回值
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
代码示例演示
public class SupplierFunction {
public static void main(String[] args) {
supplierTest(new Supplier<Integer>() { // 使用匿名内部类创建对象,并实现Supplier接口
@Override
public Integer get() { // 重写Supplier接口中的get方法
int[] arrays = new int[]{1, 3, 6, 5, 9, 2, 110, 78, 67};
Arrays.sort(arrays);
return arrays[arrays.length - 1];
}
});
}
/**
* 获取数组元素最大值
* @param supplier 提供者
*/
public static void supplierTest(Supplier<Integer> supplier){
Integer max = supplier.get();
System.out.println(max);
}
}
II. 自定义函数式接口
MyFunction<T, R>:接收一个类型为T
的参数,返回一个类型为R
的结果
接口声明
@FunctionalInterface
interface MyFunction<T, R> {
R apply(T t);
}
代码示例演示
public class Main {
public static void main(String[] args) {
MyFunction<Integer, Integer> square = num -> num * num;
int result = square.apply(5); // 调用apply方法计算5的平方
System.out.println(result); // 输出25
}
}
四、使用函数式接口的代码示例
1. 使用Predicate函数式接口筛选集合元素
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 使用Predicate接口筛选偶数
Predicate<Integer> evenPredicate = num -> num % 2 == 0;
List<Integer> evenNumbers = filter(numbers, evenPredicate);
System.out.println("偶数集合:" + evenNumbers);
// 使用Predicate接口筛选大于5的数
Predicate<Integer> greaterThanFivePredicate = num -> num > 5;
List<Integer> greaterThanFiveNumbers = filter(numbers, greaterThanFivePredicate);
System.out.println("大于5的数集合:" + greaterThanFiveNumbers);
}
// 筛选集合元素的通用方法
public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
List<T> filteredList = new ArrayList<>();
for (T item : list) {
if (predicate.test(item)) {
filteredList.add(item);
}
}
return filteredList;
}
}
2. 使用Function函数式接口进行数据转换和映射
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 使用Function接口将每个数乘以2
Function<Integer, Integer> multiplyByTwoFunction = num -> num * 2;
List<Integer> multipliedNumbers = map(numbers, multiplyByTwoFunction);
System.out.println("每个数乘以2:" + multipliedNumbers);
// 使用Function接口将每个数转换成字符串
Function<Integer, String> toStringFunction = num -> String.valueOf(num);
List<String> stringNumbers = map(numbers, toStringFunction);
System.out.println("每个数转换成字符串:" + stringNumbers);
}
// 数据转换和映射的通用方法
public static <T, R> List<R> map(List<T> list, Function<T, R> function) {
List<R> resultList = new ArrayList<>();
for (T item : list) {
R result = function.apply(item);
resultList.add(result);
}
return resultList;
}
}
3. 使用Consumer函数式接口对集合进行操作
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 使用Consumer接口打印每个数
Consumer<Integer> printNumberConsumer = num -> System.out.println(num);
forEach(numbers, printNumberConsumer);
// 使用Consumer接口将每个数乘以2并打印
Consumer<Integer> multiplyByTwoConsumer = num -> System.out.println(num * 2);
forEach(numbers, multiplyByTwoConsumer);
}
// 集合操作的通用方法
public static <T> void forEach(List<T> list, Consumer<T> consumer) {
for (T item : list) {
consumer.accept(item);
}
}
}