Lambda表达式

Lambda表达式

Lambda表达式是JDK1.8新特性(JDK1.8新增的特性)的一种,它允许将函数表达式作为参数传入方法中去。

1.Lambda表达式书写形式(箭头函数

左边放的是需要传递的参数->右边放的是被改造方法方法

2.Lambda表达式的使用

1.使用条件

必须是函数式接口

函数式接口:接口中仅仅定义了一个抽象方法的接口。
JDK8推出的注解@FunctionalInterface可以确保被注释的接口是函数是接口

2.感受效果(下面代码是通过传统方式,接口,Lambda改造方式实现同一个需求)

package cn.wolfcode.annotation;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

/**
 * @author: 阿落
 * @date: 2022/8/22  22:59
 */
//需求:
//①获取所有性别为男的学生
//②获取所有成绩不小于60的学生
public class StudentTest {
    private static List<Student> student = new ArrayList<>();

    static {
        student.add(new Student(Long.valueOf(1), "001", "小屁①号", "女", 100));
        student.add(new Student(Long.valueOf(2), "002", "小屁②号", "男", 20));
        student.add(new Student(Long.valueOf(3), "003", "小屁③号", "男", 90));
        student.add(new Student(Long.valueOf(4), "004", "小屁④号", "女", 40));
        student.add(new Student(Long.valueOf(5), "005", "小屁④号", "女", 70));
    }

    //需求:获取所有性别为男的学生
    //传统方法
    public static void main(String[] args) {
        List<Student> stu = new ArrayList<>();
        for (Student s : student
        ) {
            if (s.getSex().equals("男")) {
                stu.add(s);
            }
        }
        System.out.println("性别为男的学生是:" + stu);

        System.out.println("❀ ❀ ❀ ❀ ❀ ❀ ❀ 实现接口的方式  ❀ ❀ ❀ ❀ ❀ ❀ ❀");
        findStudentSex(new Myprodicte() {
            @Override
            public boolean test(Student s) {
                return s.getSex().equals("男");
            }
        });
        System.out.println("❀ ❀ ❀ ❀ ❀ ❀ ❀Lambda 方式改造  ❀ ❀ ❀ ❀ ❀ ❀ ❀");
        findStudentSex(s->s.getSex().equals("男"));

    }

    //根据定义的接口规则实现需求
    public static void findStudentSex(Myprodicte my) {
        List<Student> stu = new ArrayList<>();
        for (Student stu1 : student
        ) {
            if (my.test(stu1)) {
                stu.add(stu1);
            }
        }
        System.out.println("性别为男的学生:"+ stu);
    }
}


//接口
package cn.wolfcode.annotation;

import cn.wolfcode.annotation.Student;

/**
 * @author: 阿落
 * @date: 2022/8/23  19:04
 */
public interface Myprodicte {
    boolean test(Student s);
}

3.Lambda表达式的特点

  1. 可选类型声明:没有特殊要求不写参数类型,如果要求写,需要使用小括号将参数类型和参数括起来。
public class LambdaDemo {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.forEach(list1 -> System.out.println(list1));
    }
}
  1. 可选的参数圆括号:所改造的方法只有一个参数时不用谢小括号,没有参数或者有多个参数时小货号不能省去。
package cn.wolfcode.annotation;

import java.util.*;

/**
 * @author: 阿落
 * @date: 2022/8/23  20:30
 */
public class LambdaDemo {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.forEach(list1 -> System.out.println(list1));
        //①无参
        new Thread(() -> System.out.println("开启多线程")).start();
        //②一个参数
        list.forEach(s -> System.out.println(s));
        //③多个参数
        Map<String, String> map = new HashMap<>();
        map.put("1", "小屁①号");
        map.put("2", "小屁②号");
        map.put("3", "小屁③号");
        map.forEach((k, v) -> System.out.println(k + "::" + v));
    }
}

  1. 可选的大括号:如果主体包含了一个语句,大括号和分号都可以省略,如果方法主题包含多条代码,则需要使用大括号,并且每条语句用分号隔开。
   map.forEach((k,v)->{System.out.println(v);System.out.println(v);});
  1. 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

4.常见的函数式接口

既然Lamnda表达式能改造的必须是函数式接口,那么常见的函数式接口都有哪些类型呢?

  1. 消费型接口
  2. 供给型接口
  3. 函数型接口
  4. 断言型接口
函数式接口 参数类型 返回类型 说明
Consumer(消费型接口) T(只进不出) void 对类型为T的对象操作 方法:void accept(T t)
supplier(供给型接口) 无(只出不进) T 返回类型为T的对象 方法:T get();可用作工厂
Function<T,R>(函数型接口) T(有进有出,出的类型是java中的任意类型) R 对类型为T的对象操作,并返回结果是R类型的对象 方法:R apply(T t);
Predicate(断言型接口) T(有进有出,出的类型是boolean型) Boolean 判断类型为T的对象是否满足条件,并返回boolean值 方法:boolean test(T t)

5.演示案例

package cn.wolfcode.test;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.supplier;

/**
 * @author: 阿落
 * @date: 2022/8/23  22:45
 */
public class functionalInterfaceAPIDemo {
    //需求①:编写shop方法输出消费多少元---消费型接口Consumer<T>
    public void shop(int money, Consumer<Integer> consumer) {
        consumer.accept(money);
    }

    //需求②:编写getCode方法返回指定位数的随机验证码字符串,使用供给型的函数式接口:supplier<T>(有进有出,出为任意类型)
    public String getCode(int len, supplier<Integer> supplier) {
        //定义StringBuilder类型SB用来拼接获取到的字符串
        StringBuilder SB = new StringBuilder();
        //根据用户传入的参数获取指定个数的字符
        for (int i = 0; i <= len; i++) {
            //调用函数型接口supplier中的get方法获取字符并拼接
            SB.append(supplier.get());
        }
        //SB为StringBuilder类型,转为String类型
        return SB.toString();
    }

    //需求③:编写getStringRealLength方法获取字符串的真实长度
    public int getStringRealLength(String str, Function<String, Integer> fun) {
        return fun.apply(str);
    }

    //需求④:编写getString方法获取长度大于等于5的字符串。
    public List<String> getString(List<String> list, Predicate<String> predicate) {
        List<String> list1 = new ArrayList<>();
        for (String str : list
        ) {
            if (predicate.test(str)) {
                list1.add(str);
            }

        }
        return list1;
    }
}
package cn.wolfcode.test;

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.supplier;

/**
 * @author: 阿落
 * @date: 2022/8/24  0:57
 */
public class functionalInterfaceAPIDemoTest {
    functionalInterfaceAPIDemo fI = new functionalInterfaceAPIDemo();

    @Test
    public void shop() {
        fI.shop(10000, new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println("昨晚落总共消费了" + integer + "元。");
            }
        });
        //lambda改造
        fI.shop(100000, integer -> System.out.println("昨晚落总共消费了" + integer + "元。"));
    }

    @Test
    public void getCode() {

        System.out.println(fI.getCode(6, new supplier<Integer>() {
                    @Override
                    public Integer get() {
                        return (int) (Math.random() * 10);
                    }
                }
        ));
        //lambda改造
        System.out.println(fI.getCode(6, () -> (int) (Math.random() * 10)));
    }

    @Test
    public void getStringRealLength() {
        System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        }));
        //lambda改造
        System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", s -> s.length()));

    }

    @Test
    public void getString() {
        List<String> list = Arrays.asList("小屁", "小屁①号", "小屁爱吃屁", "小屁爱吃哈哈屁", "xiaopi");
        System.out.println(fI.getString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length() >= 5;
            }
        }));
        //lambda改造
        System.out.println(fI.getString(list, s -> s.length() >= 5));
    }
}

3.方法引用

作用:使得函数式接口的代码更加简洁(即在lambda表达式基础上进一步改造,简化)

  1. 方法引用的格式
    (1)符号标志:“::”(读作引用运算符)
    (2)“::”左侧:表示调用方法(对象名和类名(被static修饰时))
    (3)“::”右侧:表示调用方法名(不能编写(),因为方法引用只能调用已经存在的无参方法
 @Test
    public void getStringRealLength() {
        System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        }));
        //lambda改造
        System.out.println(fI.getStringRealLength("小屁爱吃哈哈屁", s -> s.length()));
        //方法引用
        System.out.println(fI.getStringRealLength("xiaopi", String::length));

    }

注意事项:

  1. 只能引用已经定义好的方法
  2. 引用的方法只写方法名(即只能引用无参方法
  3. 方法引用不能连续引用
  4. 方法引用结果不能进行关系和逻辑判断
  5. 方法引用改造的是lambda表达式,所以一定是在函数式接口中使用

4.延迟加载

指java代码命令被执行,却因为不满足条件不输出的情况,造成了性能浪费,我们可以在代码执行前先判断,满足要求就执行,不满足就不执行。(举个例子,你现在是一家蛋糕店老板,你现在要给一位顾客做个巧克力蛋糕,如果你不知道他爱不爱吃,直接做好送过去了,顾客不喜欢不要,是不是就浪费了,但你如果提前问清楚她的口味,如果喜欢就做,不喜欢就不做,是不是就避免了浪费。)

package cn.wolfcode.test;

import java.util.function.supplier;

/**
 * @author: 阿落
 * @date: 2022/8/24  20:59
 */
public class LazyTest {
    public static void main(String[] args) {
        String name = "小屁";
        String money = "100000元";
        String action = "shopping";
        isContinue("on", new supplier<String>() {
            @Override
            public String get() {
                return name + "去" + action + "花了" + money;
            }
        });


    }

    public static void isContinue(String info, supplier<String> supplier) {
        if (info.equalsIgnoreCase("on")) {
            supplier.get();
        System.out.println(supplier.get());
        }
    }
}

在这里插入图片描述

package cn.wolfcode.test;

import java.util.function.supplier;

/**
 * @author: 阿落
 * @date: 2022/8/24  20:59
 */
public class LazyTest {
    public static void main(String[] args) {
        String name = "小屁";
        String money = "100000元";
        String action = "shopping";
        isContinue("s", new supplier<String>() {
            @Override
            public String get() {
                return name + "去" + action + "花了" + money;
            }
        });


    }

    public static void isContinue(String info, supplier<String> supplier) {
        if (info.equalsIgnoreCase("on")) {
            supplier.get();
            System.out.println(supplier.get());
        }


    }
}

在这里插入图片描述

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...