Java8 Lambda表达式使用

目录

Lambda表达式介绍

Lambda表达式体验 

Lambda表达式语法

Lambda精简语法

方法引用

构造方法引用

综合案例实现 

@Functionallnterface注解

系统内置函数式接口 



Lambda表达式介绍

Java8的一个大亮点是引入Lambda表达式,使用它设计的代码更加简洁。通过Lambda表达式,可以替代我们以前经常写的匿名内部类来实现接口。Lambda表达式本质是一个匿名函数。

Lambda表达式体验 

通过一个小例子来体验一下Lambda表达式。

public class TestLambda {

    public static void main(String[] args) {
        Cal cal = new Cal() {
            @Override
            public int add(int a, int b) {
                return a+b;
            }
        };
        int c = cal.add(1,2);
        System.out.println("输出结果:" + c);
    }

    interface  Cal{
        int add(int a,int b);
    }
}

 这是我们以前的实现,匿名内部类,然后调用执行。

我们现在使用Lambda表达式来改写一下这段代码,如下

public class TestLambda {

    public static void main(String[] args) {
        Cal cal = (int a,int b)->{
            return a+b;
        };
        int c = cal.add(1,2);
        System.out.println("输出结果:" + c);
    }

    interface  Cal{
        int add(int a,int b);
    }
}

我们发现,使用Lambda表达式来编写这段代码,代码变的更加简洁了。

Lambda表达式语法

我们来看一下这个Lambda表达式:

(int a,int b)->{return a+b;};

一般的函数类似如下:

int add(int a,int b){
        return a + b;
}

返回值、方法名、参数列表、方法体

Lambda表达式函数的话,只有参数列表方法体

(参数列表)-> {方法体}

说明:

() : 用来描述参数列表;

{} : 用来描述方法体;

-> : Lambda运算符,可以叫做箭头符号,或者叫goes to  

 案例:

接口方法参数,无参,单个参数,两个参数,有返回值,没有返回值这六种情况

public class TestLambda {

    public static void main(String[] args) {
        /**
         * 无参数无返回值
         */
        Cal1 cal1=()->{
            System.out.println("无参数无返回值");
        };
        cal1.test();

        /**
         * 单个参数无返回值
         */
        Cal2 cal2=(int a)->{
            System.out.println("单个参数无返回值 a=" + a);
        };
        cal2.test(5);

        /**
         * 两个参数无返回值
         */
        Cal3 cal3=(int a,int b)->{
            System.out.println("两个参数无返回值 a+b=" + (a+b));
        };
        cal3.test(1,5);

        /**
         * 无参数有返回值
         */
        Cal4 cal4=()->{
            return 4;
        };
        System.out.println("无参数有返回值 " + cal4.test());

        /**
         * 单个参数有返回值
         */
        Cal5 cal5=(int a)->{
           return a;
        };
        System.out.println("单个参数有返回值 a=" +cal5.test(8));

        /**
         * 两个参数有返回值
         */
        Cal6 cal6=(int a,int b)->{
            return a + b;
        };
        System.out.println("两个参数有返回值 a+b=" + cal6.test(2,7));
    }

    interface Cal1{
        /**
         * 无参数无返回值
         */
        void test();
    }

    interface Cal2{
        /**
         * 单个参数无返回值
         * @param a
         */
        void test(int a);
    }

    interface Cal3{
        /**
         * 两个参数无返回值
         * @param a
         * @param b
         */
        void test(int a,int b);
    }

    interface Cal4{
        /**
         * 无参数有返回值
         * @return
         */
        int test();
    }

    interface Cal5{
        /**
         * 单个参数有返回值
         * @param a
         * @return
         */
        int test(int a);
    }

    interface Cal6{
        /**
         * 两个参数有返回值
         * @param a
         * @param b
         * @return
         */
        int test(int a,int b);
    }
}

运行结果:

Lambda精简语法

语法注意点:

  1. 参数类型可以省略。
  2. 假如只有一个参数,()括号可以省略。
  3. 如果方法体只有一条语句,{}大括号可以省略。
  4. 如果方法体中唯一的语句是return返回语句,那省略大括号{}的同时return也要省略。

改写实例:

 参数类型可以省略

public class TestLambda {

    public static void main(String[] args) {

        /**
         * 参数类型可以省略
         */
        Cal5 cal5=(a)->{
           return a;
        };
        System.out.println("参数类型可以省略 a=" +cal5.test(8));

    }

    interface Cal5{
        /**
         * 参数类型可以省略
         * @param a
         * @return
         */
        int test(int a);
    }
}

假如只有一个参数,()括号可以省略

public class TestLambda {

    public static void main(String[] args) {

        /**
         * 假如只有一个参数,()括号可以省略
         */
        Cal5 cal5=a->{
           return a;
        };
        System.out.println("输出 a=" +cal5.test(8));

    }

    interface Cal5{
        /**
         * 假如只有一个参数,()括号可以省略
         * @param a
         * @return
         */
        int test(int a);
    }
}

如果方法体只有一条语句,{}大括号可以省略

public class TestLambda {

    public static void main(String[] args) {

        /**
         * 如果方法体只有一条语句,{}大括号可以省略
         */
        Cal1 cal1=()->System.out.println("如果方法体只有一条语句,{}大括号可以省略");
        cal1.test();

        /**
         * 如果方法体只有一条语句,{}大括号可以省略
         */
        Test.Cal2 cal2=(a)->System.out.println("单个参数无返回值 a=" + a);
        cal2.test(5);

    }

    interface Cal1{
        /**
         * 如果方法体只有一条语句,{}大括号可以省略
         */
        void test();
    }

    interface Cal2{
        /**
         * 如果方法体只有一条语句,{}大括号可以省略
         * @param a
         */
        void test(int a);
    }
}

如果方法体中唯一的语句是return返回语句,那省略大括号{}的同时return也要省略

public class TestLambda {

    public static void main(String[] args) {

        /**
         * 无参数有返回值
         */
        Cal4 cal4=()->4;
        System.out.println("无参数有返回值 " + cal4.test());

        /**
         * 单个参数有返回值
         */
        Cal5 cal5=a->a;
        System.out.println("单个参数有返回值 a=" +cal5.test(8));

        /**
         * 两个参数有返回值
         */
        Cal6 cal6=(a, b)->a + b;
        System.out.println("两个参数有返回值 a+b=" + cal6.test(2,7));
    }

    interface Cal4{
        /**
         * 无参数有返回值
         * @return
         */
        int test();
    }

    interface Cal5{
        /**
         * 单个参数有返回值
         * @param a
         * @return
         */
        int test(int a);
    }

    interface Cal6{
        /**
         * 两个参数有返回值
         * @param a
         * @param b
         * @return
         */
        int test(int a,int b);
    }
}

方法引用

有时候多个Lambda表达式实现函数是一样的话,我们可以封装成通用方法,以便于维护。

这个时候可以用方法引用实现:

语法是: 对象::方法

假如是static方法,可以直接  类名::方法

实例如下:

public class TestLambda {

    public static void main(String[] args) {
        TestLambda tl = new TestLambda();
        Cal5 cal5=tl::TestA;
        System.out.println("输出结果" + cal5.test(5));

        Cal5 cal=TestLambda::TestB;
        System.out.println("输出结果" + cal5.test(10));
    }

    public int TestA(int a){
        return a - 2;
    }

    public static int TestB(int a){
        return a - 3;
    }

    interface Cal5{
        /**
         * 单个参数有返回值
         * @param a
         * @return
         */
        int test(int a);
    }
}

构造方法引用

如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用。

语法:  类名::new

实例:

先定义一个实体User,实现无参和有参构造方法

public class User {

    private String name;
    private String age;

    public User(){
        System.out.println("无参构造方法");
    }

    public User(String name,String age){
        System.out.println("有参构造方法");
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

 在定义两个接口

public class TestService {

    public static void main(String[] args) {
        /*UserService user = ()->{
            return new User();
        };
        System.out.println(user.getUser());*/

        /*UserService user = ()->new User();
        System.out.println(user.getUser());*/

        UserService user = User::new;
        System.out.println(user.getUser());

        UserService2 user2 = User::new;
        System.out.println(user2.getUser("张三","30"));

    }

    /**
     * 接口一
     */
    interface UserService {
        User getUser();
    }

    /**
     * 接口二
     */
    interface UserService2 {
        User getUser(String name,String age);
    }
}

测试结果输出:

综合案例实现 

 先定义一个实体User,实现无参和有参构造方法

public class User {

    private String name;
    private int age;

    public User(){
        System.out.println("无参构造方法");
    }

    public User(String name,int age){
        System.out.println("有参构造方法");
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

 测试结果输出:

public class TestService {

    public static void main(String[] args) {
        List<User> list = new ArrayList<>();
        list.add(new User("张三",30));
        list.add(new User("李四",28));
        list.add(new User("王五",35));
        list.add(new User("李思思",28));
        list.add(new User("舞王",32));

        System.out.println("lambda表达式集合排序");
        list.sort((u1,u2)->u1.getAge() - u2.getAge());
        System.out.println(list);

        System.out.println("lambda表达式遍历集合");
        list.forEach(System.out::println);
    }
}

@Functionallnterface注解

@Functionallnterface注解;

这个注解是函数式接口注解,所谓的函数式接口,当然首先是一个接口,然后就是这个接口里面只能有一个抽象方法。

这种类型的接口也称为SAM接口,即 Single Abstract Method interfaces

特点:

  1. 接口有且仅有一个抽象方法。
  2. 允许定义静态方法。
  3. 允许定义默认方法。
  4. 允许java.lang.Object中的public方法
  5. 该注解不是必须的,如果一个接口符合“函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@Functionallnterface,那么编译器会报错。

系统内置函数式接口 

Java8推出,是以Lambda重要特性,一起推出的,其中系统内置了一系列函数式接口。

在JDK的java.util.function包下,有一系列的内置函数式接口:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦想天涯~路在脚下

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

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

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

打赏作者

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

抵扣说明:

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

余额充值