JDK8新特性(一):Lambda表达式

1.首先来个Demo

public class LambdaDemo {
    public static void main(String[] args) {
        //开启一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("新线程执行代码");
            }
        }).start();
    }
}

分析:

   当我们以 new Thread().start() 的方式启动一个线程时,我们做了如下3件事情:

  1. 定义了一个没有名字的类(匿名类)
  2. 这个类的参数,调用的是 Runnable 接口
  3. 我们通过 new Runnable(){...}的方式创建了这个类,并重写了该接口的 run() 方法

   在这个示例中,其实我们关注的并不是 new Runnable() 这个过程,而是如下2点:

  1. run() 方法    (参数情况)
  2. {...}方法体中执行的代码

Lambda表达式的出现

    在以上Demo中,针对使用匿名内部类语法冗余的问题,JDK8推出了 Lambda 表达式。

  1. Lambda表达式体现的是函数式编程思想,只需要将要执行的代码放到函数中即可(函数就是类中的方法);
  2. Lambda表达式就是一个匿名函数,我们只需要将执行的代码放到 Lambda 表达式中即可。

Lambda表达式格式

    Lambda省去面向对象的条条框框,Lambda的标准格式由3部分组成:

(参数类型 参数名称) -> {
    方法体;
    return 返回值;
}

  格式说明: 

  1. (参数类型 参数名称):参数列表部分
  2. {...}:方法体,即要执行的代码部分
  3. ->:箭头,无实际含义,起到连接参数列表方法体的作用

Lambda 表达式的省略规则

  1. 小括号中的参数类型可以省略
  2. 如果小括号中只有一个参数,那么可以省略小括号
  3. 如果大括号中只有一条语句,那么可以同时省略大括号、return关键字及语句分号

使用Lambda表达式改造

public class LambdaDemo {
    public static void main(String[] args) {
        //匿名内部类方式
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("新线程执行代码了");
            }
        }).start();

        //体验Lambda表达式
        new Thread(() ->{
            System.out.println("Lambda表达式执行了");
        }).start();
    }
}

Lambda表达式的好处

☆ 可以简化匿名内部类,让代码更加精简

☆ Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

Lambda表达式练习

1.无参数无返回值的Lambda表达式

   ①定义一个接口类ISwim,接口中定义一个抽象方法 swimming();

/**
 * ISwim接口
 */
public interface ISwim {
    //swimming()抽象方法
    public abstract void swimming();
}

   ②定义一个方法 goSwimming(ISwim swim),注意该方法参数是一个接口类ISwim。然后 main 中调用该方法;

public class LambdaDemo {
    public static void main(String[] args) {
        //1.使用匿名内部类方式
        goSwimming(new ISwim() {
            @Override
            public void swimming() {
                System.out.println("我是匿名内部类的游泳");
            }
        });

        //2.Lambda表达式方式
        goSwimming(()->{
            System.out.println("我是Lambda表达式的游泳");
        });

    }

    //goSwimming(ISwim swim) 方法
    public static void goSwimming(ISwim swim){
        swim.swimming();
    }
}

//测试结果:
//    我是匿名内部类的游泳
//    我是Lambda表达式的游泳

2.有参数有返回值的Lambda表达式

   ①定义一个接口类ISmoke,接口中定义一个具有返回值(int)的抽象方法 smoking();

/**
 * ISmoke接口
 */
public interface ISmoke {
    //smoking()抽象方法
    public abstract int smoking(String name);
}

   ②定义一个方法 goSwimming(ISwim swim),注意该方法参数是一个接口类ISwim。然后 main 中调用该方法;

public class LambdaDemo {
    public static void main(String[] args) {
        //1.使用匿名内部类方式
        goSmoking(new ISmoke() {
            @Override
            public int smoking(String name) {
                System.out.println("匿名内部类:抽了"+ name + "牌香烟");
                return 5;
            }
        });

        //2.使用Lambda表达式方式
        goSmoking((String name)->{
            System.out.println("Lambda表达式:抽了"+ name + "牌香烟");
            return 6;
        });
    }

    //有参数有返回值的Lambda
    public static void goSmoking(ISmoke smoke){
        int i = smoke.smoking("中华");
        System.out.println("返回值:"+i);
    }
}

//测试结果:
//    匿名内部类:抽了中华牌香烟
//    返回值:5
//    Lambda表达式:抽了中华牌香烟
//    返回值:6

日常工作中的案例

       我们有一个List集合,集合中存放了 4个Person对象,Person对象中有 name,age,height 属性。对集合进行排序,我们会使用到 Collections 工具类中的 Collections.sort()方法。

      sort()方法中传递的两个参数:1.list集合   2.Comparator 比较器。我们发现 Comparator 是一个接口,所以此处也可以使用 Lambda 表达式来替代匿名内部类。

/**
 * Person实体类
 */
public class Person {

    private String name;

    private int age;

    private int height;

    public Person(String name, int age, int height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}
public class CollectionsLambdaDemo{

    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("刘德华",58,174));
        persons.add(new Person("张学友",56,176));
        persons.add(new Person("郭富城",54,171));
        persons.add(new Person("黎明",53,178));

        //1.匿名内部类,对集合进行排序
        Collections.sort(persons, new Comparator<Person>() {
            //年龄降序排序
            @Override
            public int compare(Person o1, Person o2) {
                return o2.getAge() - o1.getAge();
            }
        });

        for (Person person: persons) {
            System.out.println(person);
        }

        System.out.println("-----------------------------------");

        //2.Lambda表达式
        Collections.sort(persons,(Person o1,Person o2) ->{
            return o1.getAge() - o2.getAge();
        });

         for (Person person: persons) {
             System.out.println(person);
         }
    }
}

//测试结果:
    Person{name='刘德华', age=58, height=174}
    Person{name='张学友', age=56, height=176}
    Person{name='郭富城', age=54, height=171}
    Person{name='黎明', age=53, height=178}
    -----------------------------------
    Person{name='黎明', age=53, height=178}
    Person{name='郭富城', age=54, height=171}
    Person{name='张学友', age=56, height=176}
    Person{name='刘德华', age=58, height=174}

Lambda表达式使用的前提条件

1.方法的参数局部变量类型必须为接口!!!,才能使用Lambda

   eg:局部变量类型:(Runnable是一个接口)
       匿名内部类方式:
             Runnable r = new Runnable(){
                 @override
                 public void run(){
                     System.out.println("xxx");
                 }
             }
       这种情况,你要来个局部变量,可以使用 Lambda表达式
            Runnable r = ()-> System.out.println("xxx");

2.接口中有且仅有一个抽象方法

       JDK8中,只有一个抽象方法的接口称为函数式接口,我们就能使用 Lambda。


       针对一个接口中,是否有大于一个抽象方法?JDK8为我们新增了一个注解:@FunctionalInterface。它能够帮助我们检测这个接口是不是只有一个抽象方法,如果有两个抽象方法,则会报错。

Lambda表达式原理分析

       请跳转学习:Lambda表达式原理分析

Lambda 和 匿名内部类对比

1.所需的类型不一样

     匿名内部类,需要的类型可以使类,抽象类,接口;

     Lambda表达式,需要的类型必须是接口。

2.抽象方法的数量不一样

     匿名内部类所需的接口中抽象方法的数量随意;

     Lambda表达式所需的接口只能有一个抽象方法。

3.实现原理不同

     匿名内部类是在编译后,会形成额外的一个 类名$0 的.class文件

     Lambda 表达式实在程序运行的时候动态生成 .class 文件

总结

       当接口中只有一个抽象方法时,建议使用 Lambda 表达式;其他情况下,还是需要使用匿名内部类。


附:JDK8新特性(目录)

       本目录为 JDK8新特性 学习目录,包含JDK8 新增全部特性的介绍。

       如需了解,请跳转链接查看:我是跳转链接


博主写作不易,来个关注呗

求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙

博主不能保证写的所有知识点都正确,但是能保证纯手敲,错误也请指出,望轻喷 Thanks♪(・ω・)ノ

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: Lambda 表达式Java 8 中引入的一种新的编程方式,它允许您简洁地编写匿名函数。它的语法如下: (参数列表) -> {函数体} 例如: (int x, int y) -> x + y 这是一个接受两个 int 类型参数并返回一个 int 类型结果的 Lambda 表达式。它等价于以下匿名内部类: new BinaryOperator<Integer>() { @Override public Integer apply(int x, int y) { return x + y; } } Lambda 表达式可以被用作方法的参数或返回值。它们可以简化使用匿名内部类的代码,使代码更简洁,更易于阅读和维护。 常见用法: - 使用 Lambda 表达式替代匿名内部类 - 使用 Lambda 表达式作为参数传递给方法 - 使用 Lambda 表达式作为返回值返回 使用 Lambda 表达式需要注意几点: - Lambda 表达式只能用于函数式接口(functional interface)的实例。函数式接口是只有一个抽象方法的接口。 - 参数类型可以省略,编译器会自动推断出来。 - 如果函数体只有一条语句,则花括号和 return 关键字都可以省略。 希望这能帮助您快速理解 Lambda 表达式。 ### 回答2: 要快速理解JDK 8中的Lambda表达式,可以按照以下步骤进行: 1. 了解Lambda表达式的基本语法:Lambda表达式由参数列表、箭头符号和函数体组成。例如:(参数列表) -> 函数体。 2. 理解Lambda表达式的作用:Lambda表达式是一种简洁的语法,可用于替代匿名内部类来实现函数式接口。 3. 学习函数式接口的概念:函数式接口是只有一个抽象方法的接口。Lambda表达式可以与函数式接口相匹配,从而创建接口的实例。 4. 熟悉Lambda表达式的常用操作:Lambda表达式可以用于对集合进行遍历、过滤、映射等操作,以及作为方法参数和返回值。 5. 练习Lambda表达式的使用:通过编写一些简单的Lambda表达式示例代码,来熟悉Lambda表达式的使用方式。 6. 查阅官方文档和教程:阅读JDK 8中关于Lambda表达式的官方文档和在线教程,详细了解Lambda表达式的具体用法和特性。 7. 参考示例代码和实战经验:学习其他人使用Lambda表达式的示例代码和实战经验,可以从中获取对Lambda表达式的更深入理解。 总之,要快速理解JDK 8中的Lambda表达式,除了学习其语法和用法外,还需要与函数式接口概念相结合,并结合实际应用场景进行练习和实践。 ### 回答3: 要快速理解JDK 8中的Lambda表达式,可以按照以下步骤进行: 1. 了解Lambda表达式的概念:Lambda表达式是一种匿名函数,它可以作为参数传递给方法或保存到变量中。Lambda表达式可以简化代码,使代码更加紧凑和易读。 2. 学习Lambda表达式的语法:Lambda表达式的语法由参数列表、箭头符号和代码块组成。例如,(参数列表) -> {代码块}。 3. 掌握Lambda表达式的基本用法:可以使用Lambda表达式替代匿名内部类的写法,例如在集合的迭代中使用Lambda表达式来简化代码。 4. 熟悉Lambda表达式的常见函数式接口:JDK 8引入了函数式接口,它们与Lambda表达式紧密相关。常见的函数式接口包括Consumer、Supplier、Predicate、Function等,可以通过Lambda表达式直接实现这些接口中的抽象方法。 5. 学习Lambda表达式的变量捕获机制:Lambda表达式可以捕获外部方法的局部变量,但是被捕获的变量必须是final或实际上是final的。 6. 实践Lambda表达式的应用场景:尝试在自己的代码中使用Lambda表达式,例如使用Lambda表达式来实现排序、过滤、映射等操作,以及在多线程编程中应用Lambda表达式。 通过以上步骤,可以快速理解和应用JDK 8中的Lambda表达式。在实践中不断尝试,深入理解Lambda表达式的特性和优势,从而更好地利用Lambda表达式提升代码的简洁性和可读性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扛麻袋的少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值