美文网首页技术干货
Java8-初识Lambda

Java8-初识Lambda

作者: Jackie_Zheng | 来源:发表于2017-09-17 20:45 被阅读73次

    廉颇老矣,尚能饭否

    Java,这位已经20多岁的编程语言,称得上是编程语言界的老大哥了。他曾经攻城略地,碾压各路编程语言小弟,风光无限,不可一世。现在,也是家大业大,江湖地位,很难撼动。
    但是,这依然无法阻挡人们对其未来发展趋势的怀疑。这么多年过去了,江湖上新出来的各路小弟,悉数拿出自己的看家本领,确实让老大哥有些坐不住了,业界都在担心“廉颇老矣,尚能饭否”。
    可以肯定的一点是,如果Java仅靠吃老本来维持自己的江湖地位是非常危险的。但是,他没有这么做!今天要说的Lambda就是一个铁证。

    早在2014年,Oracle就发布了Java8,带来了让人振奋的不少新特性:

    • Lambda表达式
    • 接口的默认方法与静态方法
    • 方法引用
    • 重复注解
    • 扩展注解的支持
    • Optional
    • Stream
    • Date/Time API
    • JavaScript引擎Nashorn
    • Base64

    周边Java的程序员很多,Java8的不多,为什么

    但是从我周边来看,大家都多多少少听说过其中的一些新特性,但是切切实实把这些特性和API用起来的不多。当然,这其中原因很多。
    有些因为历史原因,很难在架构上动手脚,从Java6换到Java8只是一句话的事,但是要实行起来,可能会带来让人夜不能眠的各种雷,所以很多人在老实的框架下待着,用着上古的Java6。
    有些灵活性比较强的项目,通过一次大升级,转到了Java8阵营,但是各位码农觉得Java6或者Java7都完全够用,即便不够用或者不好用,想想又要花时间研究这些新特性,还是就这么将就着写吧。
    有些业界从业者,早已经用上这些新特性了,只是他们不在Java阵营。比如14年,我身边就有人开始用Scala在Spark下完成大数据计算的业务和数据处理了,时常能听到他们说,Scala真的是太好用了。同时,伴随着大前端的火热,驻扎在JS阵营的也是不在少数,JS灵活的语法也是让人欲罢不能。这些语言早早的具备了Java8中的面向函数编程的思想。

    Lambda

    public class ThreadWithoutLambda {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("This is runable thread");
                }
            });
    
            thread.start();
        }
    }
    

    这样的程序,是不是再熟悉不过了。仔细瞧瞧这段代表要表达的意思其实就是启动一个线程,这个线程只做了一件事——打印“This is runnable thread”。有没有那么一瞬间看这个run方法有点不顺眼,如果有请看下面的写法

    public class ThreadWithLambda {
        public static void main(String[] args) {
            Thread lambdaThread = new Thread(() -> System.out.println("This is lambda runnable thread"));
            lambdaThread.start();
        }
    }
    

    如何你用的是Java8的jdk,那么运行这两个类会发现,效果完全一样,而这,就是你听过很久的Lambda表达式的写法。如果你觉得有点意思,继续往下看。

    我们把上面Lambda写法的语句拿出来

    new Thread(() -> System.out.println("This is lambda runnable thread"))
    

    在new Thread的构造方法里,我们看到传递的值不是我们经常看到的一个变量或者一个对象。凭着感觉和对于Thread的了解,这应该是一个函数,在Java8之前,我们能想到这种传递方式应该就是匿名内部类了,从某种程度上来说,Lambda就充当了匿名内部类这样的角色,但是实现起来,比其更加简洁易读。

    除了Runnable接口的run方法,我们还有再熟悉不过的用于集合元素比较器的Comparator类,Java8之前,我们想对于一个集合采用自定义的方式排序,可以这样实现

    public class ComparatorWithoutLambda {
    
        public static void main(String[] args) {
            List<Apple> apples = Arrays.asList(new Apple(100, "green"),
                                               new Apple(150, "red"),
                                               new Apple(120, "yellow"));
    
            System.out.println(apples);
    
            Collections.sort(apples, new Comparator<Apple>() {
                @Override
                public int compare(Apple o1, Apple o2) {
                    return o1.getWeight().compareTo(o2.getWeight());
                }
            });
    
            System.out.println(apples);
        }
    }
    

    这里通过比较集合中的元素apple的weight属性,按照weight的从小到大完成自定义排序。程序执行的结果如下

    [Apple{weight=100, color='green'}, Apple{weight=150, color='red'}, Apple{weight=120, color='yellow'}]
    [Apple{weight=100, color='green'}, Apple{weight=120, color='yellow'}, Apple{weight=150, color='red'}]
    

    附上Apple类的实现

    public class Apple {
        private Integer weight;
        private String color;
    
        public Apple() {
        }
    
        public Apple(int weight, String color) {
            this.weight = weight;
            this.color = color;
        }
    
        public Integer getWeight() {
            return weight;
        }
    
        public void setWeight(Integer weight) {
            this.weight = weight;
        }
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    
        @Override
        public String toString() {
            return "Apple{" +
                    "weight=" + weight +
                    ", color='" + color + '\'' +
                    '}';
        }
    }
    

    使用Lambda的方式实现,同样很简洁,很惊艳

    public class ComparatorWithLambda {
    
        public static void main(String[] args) {
            List<Apple> apples = Arrays.asList(new Apple(100, "green"),
                                               new Apple(150, "red"),
                                               new Apple(120, "yellow"));
    
            System.out.println(apples);
            Collections.sort(apples, (Apple apple1, Apple apple2) -> apple1.getWeight().compareTo(apple2.getWeight()));
            System.out.println(apples);
        }
    }
    

    Lambda语法

    下面通过上面的例子看看Lambda的构成


    Lambda表达式可以理解为可传递匿名函数的一种方式。没有名称,有参数、函数体和返回类型。

    • 匿名——他确实没有像普通函数那样有自己的名字,先前的匿名函数也是如此
    • 参数——上面的a1和a2就是参数,可以对应到没用Lambda时函数参数的声明
    • 函数体——就是上面的“apple1.getWeight().compareTo(apple2.getWeight())”,相当于没有Lambda中的compare函数的函数体
    • 返回类型——从函数体,我们可以推断(专业来说叫做类型推断)函数体返回的是一个boolean类型。
    • 箭头——将参数与函数体隔开

    Lambda的语法主要有两种形式
    (parameters) -> expression
    (paramters) -> {statemenst;}
    可要仔细看好这两种表达式语法,像(String s) -> return "hello world," + s;这种可不能成为Lambda表达式。

    Lambda写法的应用举例

    (List<String> list) -> list.isEmpty(); ​布尔表达式
    () -> new Apple(10); 创建一个对象
    (Apple a) -> {System.out.println("a.getColor");} 消费一个对象
    (Stirng s) -> s.length(); 从对象中选择、抽取
    (int a, int b) -> a+b; ​ 组合两个值

    今天先到这吧~~~

    相关文章

      网友评论

        本文标题:Java8-初识Lambda

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