本节是 lambda 表达式的一个入门课, 讲解的同时配有练习 demo
前言什么是 lambda 表达式? 基础语法函数式接口自己实现一个函数式接口 jdk 提供的函数式接口 ConsumersupplierfunctionPredicate 其他场景
前言
lambda 表达式是 java8 推出的一个新特性. 标志着从 jdk1.8 开始, java 正式支持函数式编程. 使用 lambda 表达式可以用简洁流畅的代码完成一个功能, 这也在一定程度上, 可以减轻了 java 一直为人诟病的代码简洁性问题.
什么是 lambda 表达式?
lambda 表达式可以简单理解为一段可以传递的代码, 核心思想是将面向对象中传递数据变为传递行为. 下面举一个编写线程的例子.
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- System.out.println("hello lambda");
- }
- };
这里使用的是匿名内部类的方式. 匿名内部类实现的也是将代码作为数据传递, 不过使用匿名内部类还是不够简洁, 那么使用 lambda 表达式的代码是什么样的呢?
1Runnable runnable = () -> System.out.println("hello lambda");
我们可以看到使用 lambda 表达式实现起来非常的简单, 只需要一行代码即可, 接下来我们就试着分析一下这段代码.
基础语法
我们可以将 lambda 表达式整体看作是一个函数,()存放的是函数的操作数 ->指向的是函数的逻辑, 可以用 {} 包裹起来.
函数式接口
我们可以看到上述的示例代码, lambda 表达式的引用变量是一个 runnable 类型, 事实上, java 为我们提供了多种变量类型供我们选择, 这些类型我们称之为函数式接口.
函数式接口是只有一个方法的接口, 用作 lambda 表达式的类型. 比如我们之前提到的 Runnable 接口
- @FunctionalInterface
- public interface Runnable {
- /**
- * When an object implementing interface <code>Runnable</code> is used
- * to create a thread, starting the thread causes the object's
- * <code>run</code> method to be called in that separately executing
- * thread.
- * <p>
- * The general contract of the method <code>run</code> is that it may
- * take any action whatsoever.
- *
- * @see java.lang.Thread#run()
- */
- public abstract void run();
- }
我们可以看到 interface 上一个注解 @FunctionInterface, 它的作用是告诉编译器这个接口是一个函数式接口.
自己实现一个函数式接口
我们可以自己实现一个函数式接口, 判断数据的数据是否合法
- /**
- * 自定义函式数接口
- *
- * @author jialin.li
- * @date 2020-03-18 14:22
- */
- @FunctionalInterface
- public interface CustomFunctionInterface<T> {
- boolean legal(T t);
- }
测试方法:
- /**
- * 测试.
- *
- * @author jialin.li
- * @date 2020-03-18 14:23
- */
- public class Test {
- public boolean legal(int value, CustomFunctionInterface<Integer> functionInterface){
- return functionInterface.legal(value);
- }
- public static void main(String[] args) {
- System.out.println(new Test().legal(-8, (x) -> x >= 0));
- }
- }
测试结果:
1false
jdk 提供的函数式接口
jdk 在 java.util.function 中为我们提供了非常丰富的函数式接口, 大致可以分为 4 类:
接下来我们会针对这四种不同的接口, 给出相应的 demo, 你也可以先看题目, 自己尝试写一下
Consumer
将输入的 10 进制数, 转换为 2 进制数输出
- public void toBinaryString(int value, Consumer<Integer> consumer){
- consumer.accept(value);
- }
- public static void main(String[] args) {
- new Test().toBinaryString(15, (x) -> System.out.println(Integer.toBinaryString(x)));
- }
- supplier
生成 n 个随机数 100 以内的随机数, 以数组的形式返回
- public int[] getRandomArr(int n, Supplier<Integer> supplier) {
- int[] arr = new int[n];
- for (int i = 0; i < n; i++) {
- arr[i] = supplier.get();
- }
- return arr;
- }
- public static void main(String[] args) {
- int[] arr = new Test().getRandomArr(10, () -> new Random().nextInt(100));
- System.out.println(Arrays.toString(arr));
- }
- function
生成一个 [1,n] 组成的阶乘数组, 例如输入 3, 返回[1,4,9]
- public int[] getFactorialArr(int n, Function<Integer,Integer> function) {
- int[] arr = new int[n];
- for (int i = 1; i <= n; i++) {
- arr[i - 1] = function.apply(i);
- }
- return arr;
- }
- public static void main(String[] args) {
- int[] arr = new Test().getFactorialArr(10, (x) -> x*x);
- System.out.println(Arrays.toString(arr));
- }
- Predicate
判断一个数是否是偶数
- public boolean isEven(int n, Predicate<Integer> predicate) {
- return predicate.test(n);
- }
- public static void main(String[] args) {
- boolean isEven = new Test().isEven(1102, (x) -> (x % 2 == 0));
- System.out.println(isEven);
- }
其他场景
除了上述的 4 个接口, java.util.function 中还有许多其他的接口, 可以实现各种功能. 比如实现 2 个数的加法运算:
- public static void main(String[] args) {
- BinaryOperator<Integer> binaryOperator = Integer::sum;
- System.out.println(binaryOperator.apply(1, 3));
- }
实现 List 遍历:
- public static void main(String[] args) {
- List<String> list = new ArrayList<>(Arrays.asList("java", "python", "go", "sql"));
- list.forEach(System.out::println);
- }
更多场景还请您去探索, 感受函数式编程的魅力吧
最后, 期待您的订阅和点赞, 专栏每周都会更新, 希望可以和您一起进步, 同时也期待您的批评与指正!
来源: https://www.cnblogs.com/nedulee/p/12520362.html