一文带你掌握Java8中函数式接口的使用和自定义
作者:努力的IT小胖子
函数式接口是 Java 8 引入的一种接口,用于支持函数式编程。函数式接口通常包含一个抽象方法,可以被 Lambda 表达式或方法引用所实现。在本文中,我们将深入探讨函数式接口的概念、用途以及如何创建和使用函数式接口。
什么是函数式接口
函数式接口是只包含一个抽象方法的接口。但是默认方法和静态方法在此接口中可以定义多个。Java 中的函数式接口可以被用作 Lambda 表达式的目标类型。通过函数式接口,可以实现更简洁、更具可读性的代码,从而支持函数式编程的思想。
常见函数式接口
Java 中有一些内置的函数式接口,用于不同的用途:
- Runnable: 用于描述可以在单独线程中执行的任务。
- Callable: 类似于 Runnable,但可以返回执行结果或抛出异常。
- Comparator: 用于比较两个对象的顺序。
- Function: 接受一个参数并产生一个结果。
- Predicate: 接受一个参数并返回一个布尔值,用于判断条件是否满足。
- Supplier: 不接受参数,但返回一个值。
自定义函数式接口
自定义函数式接口是需要在接口上添加 @FunctionalInterface
注解
定义 CustomFunctionalInterface 接口函数
@java.lang.FunctionalInterface public interface CustomFunctionalInterface { void execute(); }
在上述代码中,定义了一个名为 CustomFunctionalInterface
的函数式接口,其中包含一个抽象方法 execute
,这是一个无参无返回值的方法。通过使用 @FunctionalInterface
注解,明确告诉编译器这是一个函数式接口,确保它只包含一个抽象方法。
基于 CustomFunctionalInterface 使用
public class CustomFunctionInterfaceTest { public void test(CustomFunctionalInterface functionalInterface) { functionalInterface.execute(); } @Test public void execute() { test(() -> System.out.println("Hello World Custom!")); } }
在测试类 CustomFunctionInterfaceTest
中,定义了一个名为 test
的方法,接受一个 CustomFunctionalInterface
参数,并在方法体中调用了 execute
方法。这个方法允许将任意实现了 CustomFunctionalInterface
的 Lambda 表达式传递进来,并执行其 execute
方法。
在测试方法 execute
中,通过调用 test
方法,传递了一个 Lambda 表达式 () -> System.out.println("Hello World Custom!")
。这个 Lambda 表达式实现了 CustomFunctionalInterface
的抽象方法 execute
,即打印了一条 "Hello World Custom!" 的消息。
常见函数式接口基本使用
Predicate
当涉及到对集合或数据进行筛选时,Java 中的函数式接口 Predicate
可以发挥重要作用。Predicate
是一个通用的函数式接口,用于定义一个接受参数并返回布尔值的操作,用于判断条件是否满足。
Predicate 函数式接口
@FunctionalInterface public interface Predicate<T> { boolean test(T t); }
基于 Predicate 进行筛选
import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; public class PredicateExample { public static List<String> filterStrings(List<String> list, Predicate<String> predicate) { List<String> filteredList = new ArrayList<>(); for (String str : list) { if (predicate.test(str)) { filteredList.add(str); } } return filteredList; } public static void main(String[] args) { List<String> stringList = List.of("apple", "banana", "cherry", "date", "elderberry"); Predicate<String> lengthPredicate = str -> str.length() > 5; List<String> longStrings = filterStrings(stringList, lengthPredicate); System.out.println("Long strings: " + longStrings); } }
在这个示例中,我们定义了一个 filterStrings
方法,它接受一个字符串列表和一个 Predicate
参数,并返回符合条件的字符串列表。在 main
方法中,我们创建了一个长度判断的 Predicate
,然后使用它来筛选出长度大于 5 的字符串。
Consumer
函数式接口 Consumer
在 Java 中用于表示接受一个参数并且没有返回值的操作。它可以用于执行一些对输入数据的处理,例如打印、修改等。
Consumer 函数式接口
@FunctionalInterface public interface Consumer<T> { void accept(T t); }
基于 Consumer 进行筛选
import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; public class ConsumerExample { public static void processIntegers(List<Integer> list, Consumer<Integer> consumer) { for (Integer num : list) { consumer.accept(num); } } public static void main(String[] args) { List<Integer> integerList = List.of(1, 2, 3, 4, 5); Consumer<Integer> squareAndPrint = num -> { int square = num * num; System.out.println("Square of " + num + " is: " + square); }; processIntegers(integerList, squareAndPrint); } }
在这个示例中,我们定义了一个 filterStrings
方法,它接受一个字符串列表和一个 Predicate
参数,并返回符合条件的字符串列表。在 main
方法中,我们创建了一个长度判断的 Predicate
,然后使用它来筛选出长度大于 5 的字符串。
在这个示例中,我们定义了一个 processIntegers
方法,它接受一个整数列表和一个 Consumer
参数,并在方法内遍历列表,对每个元素执行 accept
方法。在 main
方法中,我们创建了一个 Consumer
实现 squareAndPrint
,它会计算每个元素的平方并打印出来。
Function
函数式接口 Function
在 Java 中用于表示一个接受一个参数并产生一个结果的操作。它可以用于执行各种转换、映射和处理操作。
Function 函数式接口
Function
接口定义了一个名为 apply
的抽象方法,接受一个参数并返回一个结果。这个接口用于表示一个对输入数据的转换操作。
@FunctionalInterface public interface Function<T, R> { R apply(T t); }
在上述定义中,T
表示输入类型,R
表示输出类型。
基于 Function 进行数据转换
转换为大写
import java.util.function.Function; public class FunctionExample { public static String convertToUpperCase(String input, Function<String, String> function) { return function.apply(input); } public static void main(String[] args) { String original = "hello world"; String upperCase = convertToUpperCase(original, str -> str.toUpperCase()); System.out.println(upperCase); } }
在这个示例中,我们定义了一个 convertToUpperCase
方法,它接受一个字符串和一个 Function
参数,用于将输入字符串转换为大写。在 main
方法中,我们通过传递一个 Function
实现来执行转换操作。
字符串长度映射
import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; public class FunctionExample { public static List<Integer> mapStringLengths(List<String> list, Function<String, Integer> function) { return list.stream() .map(function) .collect(Collectors.toList()); } public static void main(String[] args) { List<String> strings = List.of("apple", "banana", "cherry", "date"); List<Integer> lengths = mapStringLengths(strings, str -> str.length()); System.out.println(lengths); } }
在这个示例中,我们定义了一个 mapStringLengths
方法,它接受一个字符串列表和一个 Function
参数,用于将输入字符串映射为它们的长度。通过使用 map
操作,我们在列表中的每个字符串上执行了长度映射。
Supplier
函数式接口 Supplier
在 Java 中用于表示一个不接受参数但产生一个结果的操作。它通常用于延迟计算,只在需要时才执行操作并生成结果。
Supplier 函数式接口
Supplier
接口定义了一个名为 get
的抽象方法,用于获取一个结果。这个接口用于表示一个无参操作,只产生结果。
javaCopy code @FunctionalInterface public interface Supplier<T> { T get(); }
在上述定义中,T
表示结果的类型
基于 Supplier 进行延迟计算
随机数生成
import java.util.Random; import java.util.function.Supplier; public class SupplierExample { public static int generateRandomNumber(Supplier<Integer> supplier) { return supplier.get(); } public static void main(String[] args) { Supplier<Integer> randomSupplier = () -> new Random().nextInt(100); int randomNumber = generateRandomNumber(randomSupplier); System.out.println("Random number: " + randomNumber); } }
在这个示例中,我们定义了一个 generateRandomNumber
方法,它接受一个 Supplier
参数,并通过调用 get
方法获取随机数。在 main
方法中,我们创建了一个随机数生成的 Supplier
,然后将它传递给 generateRandomNumber
方法来获取随机数。
延迟初始化
import java.util.function.Supplier; public class SupplierExample { private String expensiveResource = null; public String getExpensiveResource(Supplier<String> supplier) { if (expensiveResource == null) { expensiveResource = supplier.get(); } return expensiveResource; } public static void main(String[] args) { Supplier<String> resourceSupplier = () -> { System.out.println("Initializing expensive resource..."); return "Expensive Resource"; }; SupplierExample example = new SupplierExample(); System.out.println(example.getExpensiveResource(resourceSupplier)); System.out.println(example.getExpensiveResource(resourceSupplier)); } }
在这个示例中,我们定义了一个 getExpensiveResource
方法,它接受一个 Supplier
参数,并使用延迟初始化的方式获取昂贵的资源。在 main
方法中,我们创建了一个资源初始化的 Supplier
,然后多次调用 getExpensiveResource
方法,观察只有在需要时才会初始化资源。
到此这篇关于一文带你掌握Java8中函数式接口的使用和自定义的文章就介绍到这了,更多相关Java8函数式接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!