函数(Lambda)表达式学习

引言

在写多线程代码的时候我们往往为了实现多线程程序就不得不创建一些匿名内部类,但创建匿名内部类不是目的,我们的目的是为了实现多线程程序而不是为了实现匿名内部类,所以在这个过程中创建匿名内部类就显得冗余少许。

Lambda的思想及案例

Lambda表达式思想

Lambda表达式以结果为导向,这也符合"老板的基本思想",老板只管你做成了什么,而从来都不关心你做了什么,你付出了多少的努力,lambda表达式的思想本质与"老板"的思想一致。
当我们去创建多线程程序时就不得不创建一些类,这些类又显得那么的冗余。示例代码如下。
RunnableImpl类代码:

public class RunnableImpl implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" 新线程创建了");
    }
}

测试类

public class Demo01Runnable {
    public static void main(String[] args) {
        //创建Runnable接口的实现类对象
        RunnableImpl run = new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类
        Thread t = new Thread(run);
        //调用start方法开启新线程,执行run方法
        t.start();
        //简化代码,使用匿名内部类,实现多线程程序
        Runnable r = new Runnable(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" 新线程创建了");
            }
        };
        new Thread(r).start();
        //简化代码
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" 新线程创建了");
            }
        }).start();
    }
}

代码运行结果
在这里插入图片描述
从上述案例中可以看出,在创建Runnable多线程程序的过程中,不得不new Thread 对象和RunnableImpl 对象,为了解决这种代码冗余的问题,Lambda表达式就登上jdk的史前大舞台了,下文则重点阐述Lambda表达式是如何解决代码冗余的。

Lambda表达式的使用方法

案例一

本小结重点介绍多线程程序的lambda表达式实现,先上代码

public class Demo02Lambda {
    public static void main(String[] args) {
        new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" 新线程创建了");
            }
        }).start();

        //使用Lambda表达式,实现多线程
        new Thread(()->{
                System.out.println(Thread.currentThread().getName()+" 新线程创建了");
            }
        ).start();
        //优化省略Lambda
        new Thread(()->System.out.println(Thread.currentThread().getName()+" 新线程创建了")).start();
    }
}

两种方式的最大区别在于通过Lambda表达式我们可以省略创建RunnableImpl对象,Lambda表达式可以直接调用Runnable接口中的run方法

案例二

当我们需要调用的方法中存在存在参数时,lambda表达式子也可以给我搞定,下面探讨一下案例,案例的要求是在数组中存入个人信息,然后按照年龄大小排序,小猿先将案例代码呈上。
person类

public class Person {
    private String name;
    private int age;
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", 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;
    }
}

测试类

public class DemoTest {
    public static void main(String[] args) {
        System.out.println("请输入人数: ");
        Scanner sc = new Scanner(System.in);
        String next = sc.nextLine();
        int arraysIndex = Integer.parseInt(next);
        Person01[] person01s = new Person01 [arraysIndex];
        System.out.println("总共创建了"+person01s.length+"个人的模板");
        System.out.println("-------------------------------");
        System.out.println("请输入您要输入的人物信息--->"+"格式信息::"+"-> 赵丽颖,31");
        //安装
        for (int i = 0; i < person01s.length; i++) {
            System.out.println("正在输入第"+(i+1)+"个人的信息");
            String s = sc.nextLine();
            String[] split = s.split(",");
            person01s[i] = new Person01();
            person01s[i].setName(split[0]);
            person01s[i].setAge(Integer.parseInt(split[1]));
        }
        //采用普通方式
        /*Arrays.sort(person01s, new Comparator<Person01>() {
            @Override
            public int compare(Person01 o1, Person01 o2) {
                return o1.getAge()-o2.getAge();
            }
        });*/
        //采用lambda表达式
        /*Arrays.sort(person01s,(Person01 o1,Person01 o2)->{
            return  o1.getAge()-o2.getAge();
        });*/
        Arrays.sort(person01s,(o1,o2)->o1.getAge()-o2.getAge());
        System.out.println("-------------------------");
        for (int i = 0; i < person01s.length; i++) {
            System.out.println(person01s[i].getName()+"-->"+person01s[i].getAge());
        }

    }
}

测试结果
在这里插入图片描述
测试结果表明用lambda完美解决了排序问题。

案例三

前两个案例中,主要使用jdk自带的interface来实现实现lambda表达式,如Runnable、Comparator接口,在案例三中小猿将使用自定义接口,实现lambda表达式直接使用函数的过程。
案例中实现一个简单的加法计算过程

加法接口

public interface Multiplication {
    public abstract  Double mul(Double a, Double b);
}

测试类

public class Demo02Mul {
    public static void main(String[] args) {
        System.out.println("请输入两个相乘的数:");
        System.out.println("请输入第一个数;");
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        double a = Double.parseDouble(s);
        System.out.println("请输入第二个数;");
        s=sc.nextLine();
        double b = Double.parseDouble(s);
        System.out.println("计算结果是:");
        /*muli(a, b, new Multiplication() {
            @Override
            public Double mul(Double a, Double b) {
                return a*b;
            }
        });*/
        /*muli(a,b,(Double aa, Double bb)->{
            return aa*bb;
        });*/
        muli(a,b,(aa,bb) ->  aa*bb);
    }

    private static void muli(Double a,Double b,Multiplication m){
        Double mul = m.mul(a,b);
        System.out.println(mul);
    }
}

在这里插入图片描述

总结

从上述三个案例中我们可以总结出在使用lambda表达式必要的前提条件
1、具足接口,接口中有且仅有一个抽象方法(抽象方法唯一性),抽象方法过多则导致lambda无法解析对应的函数。
2、使用Lambda必须具有上下文推断(方法的参数必须与lambda对应)。
而同理我们也可以得知lambda表达式的简化规则:
1、小括号内参数的类型可以省略;
2、如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。

猜你喜欢

转载自blog.csdn.net/xueshanfeitian/article/details/106812234
今日推荐