美文网首页
java8-lambda表达式

java8-lambda表达式

作者: lesline | 来源:发表于2018-10-14 22:48 被阅读11次

    为什么要使用java8:

    Java 几个重大版本 :
    Java 从 1995 年发布到现在,也走过 18 年了,个人认为,其中几个 java 版本都肩负着重大使命,影响甚远;
    jdk1.0 1995 年 5 月 23 日诞生,Oak 语言改名为 Java,并提出“Write Once ,Run anywhere”;
    jdk1.2 1999 年 6 月发布,将 java 划分为 J2SE,J2ME,J2EE 三大平台;
    Jdk1.4 主要是性能提升,在 2000 年时候 JAVA 成为世界上最流行的电脑语言,跟这个版本离不开关系,估计国内还有大量 的 java 应用是运行在此版本上;
    Jdk5 诞生于 2004 年,他的使命就是易用,加入 1. 泛型 2 自动装箱/拆箱 3 for-each 4 static import 5 变长参数等,
    为了表示该版本的重要性,J2SE1.5 更名为 Java SE 5.0;
    Jdk8 将在 2014 年 3 月份发布,迄今为止,可能是最大更新的 java 版本,也是令人期待的一个版本,在 Java 中引入闭包概念 对 Java 程序开发方法的影响甚至会大于 Java5 中引入的泛型特征对编程方式带来的影响。

    可以看出,jdk 8 跟 jdk 5 之间,整整相差 10 年,这 10 年期间,相继发布 jdk 6、7 都是改动不大,这也说明,java 发展确 实有点缓慢了,以致曾经的跟随者.net 在某方面超越了 java,还有基于 jvm 上的动态语言崛起,比如 Groovy、Scala 等 。java8是迄今为止java历史上最大的改变。
    java语言有个最大的问题:语言本身的语法像旧社会妇女的裹脚布又臭又长。java8(主要是 lambda 表达式)很好的解决了这个问题

    lambda表达式

    示例

    示例1:比较我们想选出绿苹果的列表,或选出重量大于150克的苹果:
    java7:

    public class Apple {
        private Integer weight = 0;
        private String color = "";
    }
    List<Apple> inventory = new ArrayList<>();
    inventory.addAll(Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red")));
    
    
    public static List<Apple> filterGreenApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();
        for (Apple apple: inventory){
            if ("green".equals(apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }
    
    public static List<Apple> filterHeavyApples(List<Apple> inventory){
        List<Apple> result = new ArrayList<>();
        for (Apple apple: inventory){
            if (apple.getWeight() > 150) {
                result.add(apple);
            }
        }
        return result;
    }
    

    java8:

    public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p){
        List<Apple> result = new ArrayList<>();
        for(Apple apple : inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }       
    List<Apple> greenApples2 = filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));
    List<Apple> heavyApples2 = filterApples(inventory, (Apple a) -> a.getWeight() > 150);
    
    

    如果把判断语句抽成公共方法,如下:

    public static boolean isGreenApple(Apple apple) {
        return "green".equals(apple.getColor()); 
    }
    
    public static boolean isHeavyApple(Apple apple) {
        return apple.getWeight() > 150;
    }
    List<Apple> greenApples = filterApples(inventory, FilteringApples::isGreenApple);
    List<Apple> heavyApples = filterApples(inventory, FilteringApples::isHeavyApple);
    

    示例2:按重量从小到大排序:

    java7:

    实现一:
    static class AppleComparator implements Comparator<Apple> {
        public int compare(Apple a1, Apple a2){
            return a1.getWeight().compareTo(a2.getWeight());
        }
    }
    inventory.sort(new AppleComparator());
    实现二:匿名类实现
    inventory.sort(new Comparator<Apple>() {
        public int compare(Apple a1, Apple a2){
            return a1.getWeight().compareTo(a2.getWeight()); 
    }});
    
    inventory.sort(new Comparator<Apple>() {
        public int compare(Apple a1, Apple a2){
            return a1.getWeight().compareTo(a2.getWeight()); 
    }});
    

    java8:

    inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));
    inventory.sort(Comparator.comparing(Apple::getWeight));
    多条件排序:
    inventory.sort((a1, a2) -> {
        if (a1.getWeight().equals(a2.getWeight())) {
            return a1.getColor().compareTo(a2.getColor());
        } else {
            return a1.getWeight().compareTo(a2.getWeight());
        }
    });
    inventory.sort(Comparator.comparing(Apple::getWeight).thenComparing(Apple::getColor));
    

    JAVA8-用lamda表达式和增强版Comparator进行排序 - CSDN博客

    Lambda表达式格式

    可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。这个定义够大的,让我们慢慢道来。
    匿名——我们说匿名,是因为它不像普通的方法那样有一个明确的名称:写得少而想得多!
    函数——我们说它是函数,是因为Lambda函数不像方法那样属于某个特定的类。但和方法一样,Lambda有参数列表、函数主体、返回类型,还可能有可以抛出的异常列表。
    传递——Lambda表达式可以作为参数传递给方法或存储在变量中。
    简洁——无需像匿名类那样写很多模板代码。

    Lambda表达式构成.png

    Lambda表达式:包括参数列表、箭头、Lambda的主体,其中Lambda主体可以包括多行,这个时候必须用大括号把它括起来。

    实现基础
    默认方法
    类型推断

    函数式接口:

    函数式接口定义且只定义了一个抽象方法。
    函数式接口很有用,因为抽象方法的签名可以描述Lambda表达式的签名。函数式接口的抽象方法的签名称为函数描述符。所以为了应用不同的Lambda表达式,你需要一套能够描述常见函数描述符的函数式接口。JavaAPI中已经有了几个函数式接口:Comparable、Runnable和Callable。

    Runnable r1 = () -> System.out.println(" Hello World 1"); // 使 用 Lambda
    Runnable r2 = new Runnable() { // 使 用 匿 名 类
        public void run() {
            System.out.println(" Hello World 2");
        }
    };
    

    java8在java.util.function包中引入了新的函数式接口:
    Java 8 中 的 常 用 函 数 式 接 口

    Java 8 中 的 常 用 函 数 式 接 口.png

    Lambdas 及 函 数 式 接 口 的 例 子

    Lambdas 及 函 数 式 接 口 的 例 子.png

    原始类型特化:是为了避免原始类型和引用类型之间的装箱拆箱

    使用示例:

    java.util.function.Function<T,R>接口定义了一个叫作apply的方法,它接受一个泛型T的对象,并返回一个泛型R的对象。如果你需要定义一个Lambda,将输入对象的信息映射到输出,就可以使用这个接口(比如提取苹果的重量,或把字符串映射为它的长度)。在下面的代码中,我们向你展示如何利用它来创建一个map方法,以将一个String列表映射到包含每个String长度的Integer列表。

    @FunctionalInterface
    public interface Function<T, R> {
        R apply(T t);
    }
    public static <T, R> List<R> map(List<T> list, Function<T, R> f) {
        List<R> result = new ArrayList<>();
        for (T s : list) {
            result.add(f.apply(s));
        }
        return result;
    }
    // [7, 2, 6]
    List<Integer> l = map(Arrays.asList(" lambdas", " in", " action"), (String s) -> s.length());
    // Lambda 是 Function 接 口 的 apply 方 法 的 实 现
    

    方法引用

    Lambda的一种快捷写法,针对单一方法的Lambda的语法糖,可读性更好

    方法引用.png

    主要分三类:
    1、静态方法的方法引用:Integer::parseInt
    2、实例方法的引用:String::length
    3、外部对象的引用:service::getByName

    第2、3的区别是,第2类是lambda参数的类是操作的类,第三种是lambda操作的类是外部已存在的类,参数只操作类的参数。


    方法引用示例.png

    lambda实现原理

    lambda表达式里面,会把lambda表达式在本类中生成一个以lambda$+数字的方法。关键点:该方法不一定是static的方法,是static还是非static,取决于lambda表达式里面是否引用了this。这就是为什么lambda表达式里面的this指向的是本地,因为他在本类里面创建了一个方法,然后把lambda表达式里面的代码放进去。

    package jdk8.lambda;
    /***
     * lambda表达式的this
    /*
    public class LambdaDemo {
        private String name = "Demo";
        public void test() {
            // lambda实现
            new Thread(() -> {
                System.out.println("这里的this指向当前的ThisDemo类:" + this.name);
            }).start();
        }
    }
    

    javap -s -v LambdaDemo.class

    javap 执行结果.jpg

    说说javap命令 - 每天一点 - 博客园
    java8 lambda表达式原理 - CSDN博客
    Java8学习笔记(4) — Lambda表达式实现方式 - CSDN博客

    相关文章

      网友评论

          本文标题:java8-lambda表达式

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