zoukankan      html  css  js  c++  java
  • Java 8 Lambda 表达式

    Java 8 Lambda 表达式

    1. Lambda 表达式的基础语法

    jdk8 中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符

    箭头操作符将 Lambda 表达式拆分成两部分:

    • 左侧:Lambda 表达式的参数列表
    • 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
    public static void main(String[] args) {
        new Thread(() -> System.out.println("lambda")).start();
    }
    

    语法格式:

    (1) 语法格式一:无参数,无返回值

    () -> System.out.println("Hello Lambda!");
    

    (2) 语法格式二:有一个参数,并且无返回值

    (x) -> System.out.println(x)
    

    (3) 语法格式三:若只有一个参数,小括号可以省略不写

    x -> System.out.println(x)
    

    (4) 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句

    Comparator<Integer> com = (x, y) -> {
       System.out.println("函数式接口");
       return Integer.compare(x, y);
    };
    

    (5) 语法格式五:若 Lambda 体中只有一条语句, return 和大括号都可以省略不写

    Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
    

    (6) 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即 “类型推断”

    (Integer x, Integer y) -> Integer.compare(x, y);
    

    2. Lambda 表达式需要 "函数式接口" 的支持

    函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解 @FunctionalInterface 修饰可以检查是否是函数式接口

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }
    

    自定义 "函数式接口":

    //需求:对一个数进行运算
    @Test
    public void test6(){
        System.out.println(operation(100, (x) -> x * x));
        System.out.println(operation(200, (x) -> x + 200));
    }
    
    public Integer operation(Integer num, MyFun mf){
        return mf.getValue(num);
    }
    
    @FunctionalInterface
    public interface MyFun {
        Integer getValue(Integer num);
    }
    

    3. Java 内置四大核心函数式接口

    函数式接口 参数类型 返回类型 类型
    Consumer消费型接口 T void void accept(T t)
    Supplier供给型接口 T T get()
    Function<T, R>函数型接口 T R R apply(T t)
    Predicate断言型接口 T boolean boolean test(T t)
    BiConsumer<T, U> T, U void void accept(T t, U u)
    UnaryOperator T T void T apply(T t)
    //Consumer<T> 消费型接口 :
    @Test
    public void test1(){
        happy(10000, (m) -> System.out.println("消费:" + m + "元"));
    } 
    
    public void happy(double money, Consumer<Double> con){
        con.accept(money);
    }
    
    
    //Supplier<T> 供给型接口 :
    @Test
    public void test2(){
        List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
    
        for (Integer num : numList) {
            System.out.println(num);
        }
    }
    
    //需求:产生指定个数的整数,并放入集合中
    public List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();
    
        for (int i = 0; i < num; i++) {
            Integer n = sup.get();
            list.add(n);
        }
    
        return list;
    }
    
    //Function<T, R> 函数型接口:
    @Test
    public void test3(){
        String newStr = strHandler("			 我大尚硅谷威武   ", (str) -> str.trim());
        System.out.println(newStr);
    
        String subStr = strHandler("我大尚硅谷威武", (str) -> str.substring(2, 5));
        System.out.println(subStr);
    }
    
    //需求:用于处理字符串
    public String strHandler(String str, Function<String, String> fun){
        return fun.apply(str);
    }
    
    //Predicate<T> 断言型接口:
    @Test
    public void test4(){
        List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
        List<String> strList = filterStr(list, (s) -> s.length() > 3);
    
        for (String str : strList) {
            System.out.println(str);
        }
    }
    
    //需求:将满足条件的字符串,放入集合中
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> strList = new ArrayList<>();
    
        for (String str : list) {
            if(pre.test(str)){
                strList.add(str);
            }
        }
    
        return strList;
    }
    

    3. 方法引用与构造器引用

    3.1 方法引用

    方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用(可以将方法引用理解为 Lambda 表达式的另外一种表现形式)

    主要有三种语法格式:

    1. 对象的引用 :: 实例方法名
    2. 类名 :: 静态方法名
    3. 类名 :: 实例方法名

    注意:

    • ①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
    • ②若 Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
    //对象的引用 :: 实例方法名
    @Test
    public void test1(){
        Employee emp = new Employee(101, "张三", 18, 9999.99);
        
        Supplier<String> sup = () -> emp.getName();
        System.out.println(sup.get());
        
        System.out.println("----------------------------------");
        
        Supplier<String> sup2 = emp::getName;
        System.out.println(sup2.get());
    }
    
    //类名 :: 静态方法名
    @Test
    public void test2(){
        Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
        Comparator<Integer> com2 = Integer::compare;
    }
    
    //类名 :: 实例方法名
    @Test
    public void test3(){
        BiPredicate<String, String> bp = (x, y) -> x.equals(y);
        BiPredicate<String, String> bp2 = String::equals;
    }
    

    3.2 构造器引用

    构造器引用 :构造器的参数列表,需要与函数式接口中参数列表保持一致!

    类名 :: new
    
    # 无参构造器
    Supplier<Employee> con1 = () -> new Employee();
    Supplier<Employee> con2 = Employee::new;
    Employee[] emps = con3.apply(20);
    
    # 一个参数的构造器
    Function<String, Employee> con3 = Employee::new;
    Employee emp3 = con3.apply("xxx");
    
    # 两个参数的构造器
    BiFunction<String, Integer, Employee> con4 = Employee::new;
    

    4 数组引用

    类型[] :: new;
    
    Function<Integer, String[]> fun = (args) -> new String[args];
    String[] strs = fun.apply(10);
    
    Function<Integer, String[]> fun2 = String[] :: new;
    String[] strs2 = fun.apply(10);
    

    Java 8 新特性

    1. Java 8 Lambda 表达式
    2. Java 8 Stream API
    3. Java 8 Optional 类深度解析
    4. Java 8 新时间日期 API
    5. Java 8 接口中的默认方法与静态方法
    6. Java 8 可重复注解与类型注解
  • 相关阅读:
    web中缓存的使用
    .net1.1 Read Byte Array From File
    数据库连接的多种方式(二)
    存储过程和SQL语句比较及存储过程在C#中调用方法(转)
    exec与sp_executesql语法的区别详解(转)
    SQL Server存储过程入门案例详解
    asp.net结合aspnetpager用sql语句分页
    数据库连接的多种方式(一)
    分页存储过程1
    asp.net结合aspnetpager使用SQL2005的存储过程分页(转)
  • 原文地址:https://www.cnblogs.com/binarylei/p/8604124.html
Copyright © 2011-2022 走看看