zoukankan      html  css  js  c++  java
  • Java8 lambda函数式编程

    Lambda 表达式是 Java SE8 推出的新功能,也是Java第一次引入函数式编程的尝试。

    Lambda表达式格式
    Lambda 表达式可以看做是一种匿名函数,但是它没有访问修饰符、返回值和名字。Lambda表达式由两部分构成,形式参数和方法体,中间用“->”符号分隔。其中的形式参数类型能够进行自动推断,可以不写。当然在某些特殊情况下,形参类型也是不可缺少的。方法体可以是简单的表达式或者代码块,下面是一些例子:

    // 1. 不需要参数,返回值为 5
    () -> 5
    // 2. 接收一个参数(数字类型),返回其2倍的值
    x -> 2 * x
    // 3. 接受2个参数(数字),并返回他们的差值
    (x, y) -> x – y
    // 4. 接收2个int型整数,返回他们的和
    (int x, int y) -> x + y
    // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
    (String s) -> System.out.print(s)

    要理解Lambda表达式,首先要了解一种特殊的接口:函数式接口。什么是函数式接口呢?简单来说就是只包含一个抽象方法的接口。Java标准库中的java.lang.Runnable和java.util.Comparator就是典型的函数式接口。对于函数式接口,我们就可以使用Lambda表达式来代替用传统匿名类来创建实例对象。
    java.util.function包
    在Java SE8之前标准库中的函数式接口并不多。JavaSE8增加了java.util.function包,里面都是可以在开发中只用的函数式接口。我们也可以自定义一个函数式接口,但最好在接口上使用@FunctionalInterface注解标明这是一个函数式接口,以免团队其它成员错误地往接口添加新的方法,当然java.util.function包中的所有接口都添加了@FunctionalInterface注解。
    函数式接口

    我们以Runnable接口为例,用传统匿名类的方式创建一个线程:

    public void runThread() {
    new Thread(new Runnable() {
    public void run() {
    System.out.println("Run!");
    }
    }).start();
    }
    上面传统匿名类方式中,我们可以看到,我们需要new一个接口名称,接口内部还要附带这个接口抽象方法的实现。而如果我们使用Lambda表达式,则代码非常简洁:

    public void runThreadUseLambda() {
    new Thread(() -> {
    System.out.println("Run!");
    }).start();
    }

    通过上面代码我们可以看到,Lambda表达式在两方面做了简化:

    首先不需要声明Runnable接口,因为这可以通过上下文推断出来
    其次不需要再写一个run方法的实现,因为函数式接口中只有一个方法
    ---------------------
    使用场景

    场景:有个User的List,需要将所有的用户ID取出来。
    List<Integer> userIds = users.stream().map(u -> u.getId()).collect(Collectors.toList());
    1
    场景:有个User的List,需要将所有的用户ID取出来,还得注意去重
    List<Integer> userIds = users.stream().map(u -> u.getId()).distinct().collect(Collectors.toList());
    1
    场景:有个User的List,需要将其放到HashMap里,key为用户ID,value为该User
    Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(User :: getId, u -> u));
    1
    场景:有个User的List,需要将其放到HashMap里,key为用户ID,value为用户名称
    Map<Integer, String> userMap = users.stream().collect(Collectors.toMap(User :: getId, u -> u.getName()));
    1
    场景:有个User的List,需要将其放到HashMap里,key为用户ID,value为该User。User可能会重复,也就是ID会重复。按照上面的做法会导致如下错误:
    Exception in thread "main" java.lang.IllegalStateException: Duplicate key 123456
    1
    /**
    * 需要指定在key重复时选择保留旧值还是新值
    */
    Map<Integer, User> userMap = users.stream().collect(Collectors.toMap(User :: getId, u -> u, (oldV, newV) -> newV));
    1
    场景:有个User的List,需要按照id的大小进行排序
    List<User> users = new ArrayList<User>();
    users.sort((u1, u2) -> u1.getId().compareTo(u2.getId()));
    ---------------------
    常用方法

    stream()、将集合变成了流,

    filter、过滤到我们所需要的,

    collect(Collectors.toList())、将得到的流对象转换为集合。 Collect()即为收集器用来将经过筛选、映射的流进行最后的整理

      groupingBy() 分组

      /joining()连接流中每个元素的toString方法生成的字符串

      /reducing()是针对单个值的收集,其返回结果不是集合家族的类型,而是单一的实体类T

      /collectingAndThen()转换函数返回的类型

      /Counting()计算流中个数/

      SummingInt()对流中元素的一个整数属性求和

      /averagingInt()计算流中元素integer属性的平均值

      maxBy()比较器选出的最大元素的optional,如果为空返回的是Optional.empty()

      minBy()比较器选出的最小元素的optional,如果为空返回的是Optional.empty()

      Collectors的常用封装有:toList()/toMap()/toCollection()/toSet()

    map() 映射

    distinct()去重

    limit(3)截取流的前N个元素

    skip(3)跳过流的前n个元素

    equels() 比较

    anyMatch()判断流中是否匹配任意元素

    allMatch()判断流中是否匹配任意元素

    noneMatch()判断流中是否未匹配所有元素

    findAny()从流中获取任意元素,返回一个Optional类型的元素

        Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:

        isPresent()
        判断容器中是否有值。
        ifPresent(Consume lambda)
        容器若不为空则执行括号中的Lambda表达式。
        T get()
        获取容器中的元素,若容器为空则抛出NoSuchElement异常。
        T orElse(T other)
        获取容器中的元素,若容器为空则返回括号中的默认值。
        ---------------------
    reduce()归约  是将集合中的所有元素经过指定运算,折叠成一个元素输出

               数值流采用reduce进行数值操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低。 
               当流操作为纯数值操作时,使用数值流能获得较高的效率。

               StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream,也提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong。 

               每种数值流都提供了数值计算函数,如max、min、sum等

    forEach()循环

    sort()排序

    sorted()排序

    Comparator()排序

    详细使用参考:https://blog.csdn.net/u010425776/article/details/52344425

  • 相关阅读:
    sprint1的个人总结及《构建之法》8、9、10章读后感
    操作系统作业----实验三
    《构建之法》第六,七章读后感
    实验二 作业调度模拟程序 报告
    参考的博客园
    复利计算器6.0
    复利计算-做汉堡,结对2.
    复利计算器5.0
    0608典型用户
    0603我的感受
  • 原文地址:https://www.cnblogs.com/Bkxk/p/11169833.html
Copyright © 2011-2022 走看看