美文网首页
JDK1.8新特性--Lambda表达式

JDK1.8新特性--Lambda表达式

作者: 沧海月明_ee9b | 来源:发表于2021-03-08 10:36 被阅读0次
     非原创,知识总结性文章
    

    1、Lambda表达式的介绍

    函数式编程思想概述

    在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”。相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做。

    传统写法代码示例

    public class demo01 {
        public static void main(String[] args) {
            Runnable runnable = new Runnable(){
                public void run(){
                    System.out.println("多线程任务执行");
                }
            };
            new Thread(runnable).start();
        }
    }
    

    说明:

    • Thread类需要Runnable接口作为参数,其中的抽象run方法是用来指定线程任务内容的核心;
    • 为了指定run的方法体,不得不需要Runnable接口的实现类;
    • 为了省去定义一个RunnableImpl实现类的麻烦,不得不使用匿名内部类;
    • 必须覆盖重写抽象run方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错;
    • 而实际上,似乎只有方法体才是关键所在

    上述示例使用Lambda的写法

    public class demo01 {
        public static void main(String[] args) {
            new Thread(()->{
                System.out.println("多线程启动");
            }).start();
        }
    }
    

    上例中,核心代码其实只是如下所示的内容:() -> System.out.println("多线程任务执行!")

    Lambda标准格式

    Lambda省去面向对象的条条框框,格式由3个部分组成:
    
    • 一些参数;
    • 一个箭头;
    • 一段代码。
      Lambda表达式的标准格式为:(参数类型 参数名称) -> { 代码语句 }
      格式说明:
    • 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔;
    • ->是新引入的语法格式,代表指向动作;
    • 大括号内的语法与传统方法体要求基本一致。

    练习:使用Lambda标准格式(无参无返回)

    给定一个厨子Cooker接口,内含唯一的抽象方法makeFood,且无参数、无返回值。如下:
    
    public interface Cooker {
        void makeFood();
    }
    

    在下面的代码中,请使用Lambda的标准格式调用invokeCook方法,打印输出“吃饭啦!”字样:

    public class demo01 {
        public static void main(String[] args) {
            invokeCook(() -> {
                System.out.println("吃饭啦!");
            });
    
        }
        private static void invokeCook(Cooker c){
            c.makeFood();
        }
    }
    

    Lambda的参数和返回值

    需求:使用Lambda表达式对存在数组中的Person类型的对象数据按照年龄的降序输出。
    

    传统写法:

    public class Demo02 {
        public static void main(String[] args) {
            // 本来年龄乱序的对象数组
            Person[] array = {
                new Person("古力娜扎", 19),
                new Person("迪丽热巴", 18),
                new Person("马尔扎哈", 20) };
    
            // 匿名内部类
            Comparator<Person> comp = new Comparator<Person>() {
                @Override
                public int compare(Person o1, Person o2) {
                    return o2.getAge() - o1.getAge();
                }
            };
            Arrays.sort(array, comp); // 第二个参数为排序规则,即Comparator接口实例
    
            for (Person person : array) {
                System.out.println(person);
            }
        }
    }
    

    Lambda写法:

    public class demo02 {
        public static void main(String[] args) {
            // 本来年龄乱序的对象数组
            Person[] array = {
                    new Person("古力娜扎", 19),
                    new Person("迪丽热巴", 18),
                    new Person("马尔扎哈", 20) };
    
            Arrays.sort(array,(Person p1,Person p2) -> {
                return p2.getAge() - p1.getAge();
            });
    
            for (Person person : array) {
                System.out.println(person);
            }
        }
    }
    

    Lambda省略格式

      Lambda强调的是“做什么”而不是“怎么做”,所以凡是可以根据上下文推导得知的信息,都可以省略。例如上例还可以使用Lambda的省略写法:
    
    public static void main(String[] args) {
        invokeCalc(120, 130, (a, b) -> a + b);
    }
    

    省略规则:
    在Lambda标准格式的基础上,使用省略写法的规则为:

    • 小括号内参数的类型可以省略;
    • 如果小括号内有且仅有一个参数,则小括号可以省略;
    • 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。
      注意:关于第三点如果省略一个,那么必须同时都得省略。

    2、Lambda表达式的应用

    Lambda表达式的使用条件是
    
    • 使用lambda表达式的类型必须是一个只含有一个抽象方法的借口
    • lambda只能使用final修饰的变量

    forEach遍历Map

    //1.forEach遍历Map
    System.out.println("\n1.forEach遍历Map");
    Map<String, Object> map = new HashMap<>();
    map.put("key1", 11);
    map.put("key2", 12);
    map.put("key3", 13);
    map.put("key4", 14);
    map.forEach((key,value)->{
        System.out.println("key:"+key+",value:"+value);
    });
    

    输出:
    1.forEach遍历Map
    key:key1,value:11
    key:key2,value:12
    key:key3,value:13
    key:key4,value:14

    forEach遍历List

    //2.forEach遍历List
    System.out.println("\n2.forEach遍历List");
    List<Integer> list =  new ArrayList<Integer>() ;
    list.add(1);
    list.add(2);
    list.add(3);
    list.forEach(value->System.out.println(value));
    

    输出:
    2.forEach遍历List
    1
    2
    3

    在多线程中使用Lambda表达式

    //3.在多线程中使用Lambda表达式
    System.out.println("\n3.在多线程中使用Lambda表达式");
    new Thread(()->System.out.println("new Thread start")).start();
    

    输出:
    3.在多线程中使用Lambda表达式
    new Thread start

    自定义Lambda表达式功能

    //4.自定义Lambda表达式功能
    interface MathOperator{
        int operator(int a, int b);
        
    }
    public static void calc(int a ,int b, MathOperator operator){
        System.out.println(operator.operator(a, b));
    }
    
    System.out.println("\n4.自定义Lambda表达式功能");
    MathOperator add = (a,b)->a+b ;
    MathOperator sub = (a,b)->a-b ;
    MathOperator mul = (a,b)->a*b ;
    MathOperator div = (a,b)->a/b ;
    
    calc(3, 5, add);
    calc(3, 5, sub);
    calc(3, 5, mul);
    calc(3, 5, div);
    

    输出:
    4.自定义Lambda表达式功能
    8
    -2
    15
    0

    Predicate接口实现数据过滤

    System.out.println("\n5.Predicate接口实现数据过滤");
    List<String> filterList = new LinkedList<>() ;
    filterList.add("1");
    filterList.add("abc");
    filterList.add("java");
    filterList.add("python2");
    filterList.add("python3");
    filterList.add("c++");
    filture(filterList, str->str.startsWith("j")) ;
    //单条件过滤
    filterList.stream().filter(str->str.contains("++")).forEach(value->System.out.println(value)) ;
    //多条件逻辑过滤
    Predicate<String> startWith = str->str.startsWith("p") ;
    filterList.stream().filter(startWith.and(str->str.contains("2"))).forEach(value->System.out.println(value)) ;
    

    输出:
    5.Predicate接口实现数据过滤
    java
    c++
    python2

    Lambda的map和reduce操作

    /3.在多线程中使用Lambda表达式
    System.out.println("\n6.Lambda的map和reduce操作");
    List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
    //map操作让每一个元素加上它之前的0.12倍
    costBeforeTax.stream().map(cost -> cost+0.12*cost).forEach(System.out::println);
    System.out.println(costBeforeTax.stream().reduce((sum,cost)->sum+cost).get()); //求和
    

    输出:
    6.Lambda的map和reduce操作
    112.0
    224.0
    336.0
    448.0
    560.0
    1500

    创建一个字符串列表,每个字符串长度大于2

    System.out.println("\n7.创建一个字符串列表,每个字符串长度大于2");
    List<String> strList = Arrays.asList(new String[]{"abc","de","abcde"});
    List<String> filtered = strList.stream().filter(x -> x.length()> 2).collect(Collectors.toList());
    System.out.printf("Original List : %s, filtered list : %s %n", strList, filtered);
    

    输出:
    7.创建一个字符串列表,每个字符串长度大于2
    Original List : [abc, de, abcde], filtered list : [abc, abcde]

    获取数字的个数、最小值、最大值、总和以及平均值

    System.out.println("\n8.获取数字的个数、最小值、最大值、总和以及平均值");
    List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
    IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
    System.out.println("Highest prime number in List : " + stats.getMax());
    System.out.println("Lowest prime number in List : " + stats.getMin());
    System.out.println("Sum of all prime numbers : " + stats.getSum());
    System.out.println("Average of all prime numbers : " + stats.getAverage());
    

    输出:
    8.获取数字的个数、最小值、最大值、总和以及平均值
    Highest prime number in List : 29
    Lowest prime number in List : 2
    Sum of all prime numbers : 129
    Average of all prime numbers : 12.9

    相关文章

      网友评论

          本文标题:JDK1.8新特性--Lambda表达式

          本文链接:https://www.haomeiwen.com/subject/sdnrqltx.html