JDK 8新特性——Lambda表达式

一、函数式编程思想概述

https://www.runoob.com/java/java8-lambda-expressions.html

在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”

面向对象强调“必须通过对象的形式来做事情”,做事情之前首先要创建一个对象

函数式思想则尽量忽略面向对象的复杂语法:”强调做什么,而不是以什么形式去做”,我们要学习的Lambda表达式就是函数式思想的体现

什么是函数式接口呢?就是一个接口有且只有一个抽象方法。

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

1.1需求:启动一个线程,在控制台输出一句话:多线程启动了

1.1.1 方式一 创建类实现Runnable接口

  • 定义一个类MyRunnable实现Runnable接口,重写run()方法

  • 创建MyRunable类对象

  • 创建Thread类的对象,把MyRunnable的对象作为构造参数传递

  • 启动线程

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("多线程程序启动了");
    }
}
public class LambdaTest {
    public static void main(String[] args) {
        MyRunnable my = new MyRunnable();
        Thread t = new Thread(my);
        t.start();

    }
}

1.1.2 方式二 匿名内部类

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("ssss");
            }
        }).start();

1.1.3 方式三 lambda表达式

简洁,不用创建类

        new Thread( ()->{
            System.out.println("多线程程序启动");
        }).start();

1.2 Lambda表达式的代码式使用分析

        new Thread( ()->{
            System.out.println("多线程程序启动");
        }).start();
  • ():里面没有内容,可以看成是方法形式参数为空

  • ->:用箭头指向后面要做的事情

  • {}:包含一段代码。我们称之为代码块

(形式参数)->{代码块}

  • 形式参数:如果有多个参数,参数之间用逗号隔开。

类似于方法的形参列表,这里指的是函数式接口中抽象方法的参数。参数的类型即可以声明也可以省略,如果只有一个参数,括号也可以省略

  • ->:由英文中划线和大于符号组成,固定写法,代表指向动作

  • 代码块:我们具体要做的事情

二、Lambda表达式练习

2.1 抽象方法无参无返回值

public interface Eatable {
    void eat();
}

public class EatableImpl implements Eatable{
    @Override
    public void eat() {
        System.out.println("好好好");
    }
}

public class EatableDemo {
    public static void main(String[] args) {
       Eatable e = new EatableImpl();
       userEatable(e);
    }

    private static void userEatable(Eatable e){
       e.eat();
    }
}

上面的代码可以简化

       userEatable(()->{
           System.out.println("好好好");
       } );

下面这个就不需要实现类的

public class EatableDemo {
    public static void main(String[] args) {

       userEatable(()->{
           System.out.println("好好好");
       } );
    }

    private static void userEatable(Eatable e){
       e.eat();
    }
}

2.1.1 匿名内部类与lambda表达式直接对比

@FunctionalInterface
public interface AcanthopanaxInterface {
    void get();
}

public class Test03 {
    public static void main(String[] args) {
//      1.使用匿名内部类的方式进行
        new AcanthopanaxInterface(){

            @Override
            public void get() {
                System.out.println("get");
            }
        }.get();

//     2.lambda表达式
        AcanthopanaxInterface acanthopanaxInterface = () -> {
            System.out.println("使用lambda表达式的调用方法");
        };
        acanthopanaxInterface.get();

    }
}

2.2 抽象方法带参无返回值

定义接口

public interface Flyable {
    void fly(String s);
}

public class FlyableDemo {
    public static void main(String[] args) {
        userFlyable( (String s)->{
            System.out.println(s);
            System.out.println("好好好");
        });
    }
    
    private static void userFlyable(Flyable f){
       f.fly("风和日丽");
    }
}

拆开看一下

public class FlyableDemo {
    public static void main(String[] args) {
        Flyable flyable = (String s) -> {
            System.out.println(s);
            System.out.println("好好好");
        };
        userFlyable(flyable);
    }
    private static void userFlyable(Flyable f){
        f.fly("风和日丽");
    }
}

2.3 抽象方法带参带返回值

public class AddableDemo {
    public static void main(String[] args) {

        userAddable( (int x,int y)->{
            return x+y;
        });
    }

    private static void userAddable(Addable a){
        int sum = a.add(10,20);
        System.out.println(sum);
    }
}

a.add(10,20)中的10和20最终传递给了int x,int y,然后通过lambda表达式将x与y相加并返回给sum

public interface Addable {
    int  add(int x,int y);
}

如果上面的不好理解我们就拆分出来

一定要看一下注释信息

public class AddableDemo {
    public static void main(String[] args) {
//        Addable addable = (x, y) -> {
//            return x + y;
//        };
//      下面的程序就是这句话userAddable(addable);
        userAddable((x, y) -> {
            return x + y;
        });
    }

    private static void userAddable(Addable a){
        int sum = a.add(10,20);
        System.out.println(sum);
    }
}

2.3.1 匿名内部类与lambda表达式的对比

@FunctionalInterface
public interface YouShenInterface {
    String get(int i,int j);
}
public class Test04 {
    public static void main(String[] args) {
//      1.匿名内部类的形式
        YouShenInterface youShenInterface = new YouShenInterface() {
            @Override
            public String get(int i, int j) {
                return i + "---" + j;
            }
        };
        System.out.println(youShenInterface.get(1,1));

//     2. lambda表达式的形式
        YouShenInterface youShenInterface1 = (i, j) -> {
            return i + "---" + j;
        };
        System.out.println(youShenInterface1.get(1,2));

    }
}

三、Lambda表达式的省略模式

3.1 参数的类型可以省略

虽然能省略,但是多个参数的情况下不能只省略一个

        userAddable( ( x, y)->{
            return x+y;
        });

3.2 参数有且只有一个,参数可以省略

public class FlyableDemo {
    public static void main(String[] args) {
        userFlyable(  s->{
            System.out.println(s);
        });
    }

    private static void userFlyable(Flyable f){
       f.fly("风和日丽");
    } 
}

3.3 代码块语句只有一条,可以省略大括号和分号

public class FlyableDemo {
    public static void main(String[] args) {
        userFlyable(  s->System.out.println(s) );
    }

    private static void userFlyable(Flyable f){
       f.fly("风和日丽");
    } 
}

3.4 代码块语句只有一条,return也要省略掉

        userAddable( ( x, y)-> x+y);

四、注意事项

  • 有一个接口(抽象类不可以),接口中有且只有一个抽象方法

  • 使用lambda的时候必须有上下文环境,才能推导出Lambda对应的接口

匿名内部类编译之后会多出一个“.class”文件,而lambda不会多出,lambda字节码会在运行的时候动态生成

匿名内部类可以是接口,可以是抽象类,还可以是具体类

  • @ FunctionalInterface 表示该接口为函数接口

@FunctionalInterface
public interface OrderService {
    void get();
}

如下图所示,如果我们再增加一个方法,就会报错

但是我们可以写默认方法

  • Object父类中的方法可以在函数接口中重写

五、集合的遍历与排序

5.1 集合的遍历

public class Test06 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("mayikt");
        arrayList.add("zhangin");
        arrayList.add("asdasfg");

//      1.匿名内部类的形式
        arrayList.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
//      2.lambda表达式的形式
        arrayList.forEach(s->{
            System.out.println(s);
        });

    }
}

5.2 集合的排序

public class Test07 {
    public static void main(String[] args) {
        ArrayList<UserEntity> userEntityArrayList = new ArrayList<>();
        userEntityArrayList.add(new UserEntity("zhangjingqi",30));
        userEntityArrayList.add(new UserEntity("fanusbisf",18));
        userEntityArrayList.add(new UserEntity("saffawfasx",25));
//      1.匿名内部类排序
        userEntityArrayList.sort(new Comparator<UserEntity>() {
            @Override
            public int compare(UserEntity o1, UserEntity o2) {
                return o1.getAge()-o2.getAge();
            }
        });
        userEntityArrayList.forEach((userEntity)->{
            System.out.println(userEntity);
        });

        System.out.println("*************************************");
//      2.lambda表达式排序
        userEntityArrayList.sort((o1,o2)->{
            return  o1.getAge()-o2.getAge();
        });
        userEntityArrayList.forEach((userEntity)->{
            System.out.println(userEntity);
        });
    }
}
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我爱布朗熊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值