美文网首页
java8 lambda

java8 lambda

作者: itsenlin | 来源:发表于2018-05-13 17:53 被阅读0次

    定义

    “Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。

    java8增加了对函数式编程的支撑,即java8 lambda表达式。通过lambda表达式可以方便程序员将代码作为数据进行传递,可以赋值给一个变量也可以作为函数参数、返回值来使用,类似于java的匿名内部类。

    入门例子

    当前开发使用最多的就是多线程,

    • 在java中一般是通过实现Runnable接口,如下
      new Thread(new Runnable() {
        @Override
        public void run() {
        System.out.println("Hello world!");
        }
      }).start();
      
    • 在java8中可以使用lambda表达式形式,更简单,如下
      new Thread( () -> System.out.println("Hello world!") ).start();
      

    java8 lambda语法

    • 基本语法
      (parameters) -> expression

      (parameters) ->{ statements; }

    说明:parameters可以带参数类型也可以省略参数类型,但省略参数类型时必须能保证jdk自动推断

    • 函数接口

    函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型,可以使用@FunctionalInterface注解标注。接口中单一方法的命令并不重要,只要方法签名和Lambda表达式的类型匹配。

    • JDK中默认提供的函数接口
    接口 参数 返回类型 示例
    Predicate<T> T boolean 判断结果的真假,是与否等
    Consumer<T> T void 输出一个值,像上面线程
    Function<T,R> T R 获得一个对象的名字
    Supplier<T> None T 工厂方法
    UnaryOperator<T> T T 逻辑非(!)
    BinaryOperator<T> (T,T) T 求两个数的乘积(*)

    java8 Stream

    java8 不仅在语言层面支持了lambda表达式,还为此对类库做了改进,包括集合类的API以及引入的流(Stream),Stream很多方法的参数都是lambda表达式。

    • 内部迭代和外部迭代
      相对于集合代码来说的,像常用的for/while循环通过产生新的Iterator对象来控制整个迭代过程,就是外部迭代。而java8中集合对你的stream()方法直接是使用Stream对集合中的数据进行迭代,就是内部代码。

            List<String> list = new ArrayList<>();
            list.add("hello");
            list.add("world");
            list.add("!");
      
            //外部迭代
            for (String s : list) {
                System.out.println(s);
            }
      
            //内部迭代
            list.stream().forEach(e -> System.out.println(e));
      
    • 惰性求值
      在Stream的操作中,有一些像filter方法只描述Stream,并不会产生一个新的集合的方法,叫做惰性求值方法;就像医生开的药方,并不是具体的药品。

    • 及早求值
      在Stream的操作中,还有一类像count这种方法最终会从Stream中产生最终值,叫做及早求值方法;这个已经是根据药方获取到相应药品了。

    判断惰性求值还是及早求值很简单:返回Stream对象就是惰性求值;返回另外类型的值或者空,则是及早求值。
    对Stream最理想的操作是形成一个惰性求值链,最后用一个及早求值的操作返回想要的结果。

            long num = list.stream().filter(s -> s.length() > 2).count();
            System.out.println("num: " + num);
    ----------------------------------------------------------
    输出:num: 2
    

    java8 常用的Stream操作

    • collect(toList())
      将一个流中的值生成一个列表,及早求值函数。是一个通用的结构。
    List<String> list = Stream.of("hello", "world", "!").collect(Collectors.toList());
    
    • map
      如果一个函数可以将一种类型的值转换成另外一种类型,则map就可以使用此函数将一个流中的值转换成一个新的流。例如将字符串字符全大写
    List<String> collect = Stream.of("hello", "world", "!").map(s -> s.toUpperCase()).collect(Collectors.toList());
    collect.stream().forEach(s -> System.out.print(s + " "));
    ------------------------------------------------------
    输出:HELLO WORLD ! 
    

    map函数接收一个Function<T,R>类型的参数。

    • filter
      遍历数据并检查其中的元素是filer的本职工作。例子可以参考前面的。

    filter函数增收一个Predicate<T>类型的参数

    • flatMap
      与map类似,可以将Stream中的值进行替换;与map不一样的是flatMap可以将多个Stream连接成一个Stream
    List<String> together = Stream.of(asList("a", "b"), asList("c", "d")).flatMap(s -> s.stream()).collect(Collectors.toList());
    

    与map一样接收一个Function<T,R>类型参数,不过R的类型限定为一个Stream类型。

    • max和min
      Stream上常用的操作之一是求最大或者最小值。这个要考虑的是用什么作为排序的指标,例如数值大小、字符串长度、字典序等等。
    System.out.println("max: " + Stream.of(asList(1, 2), asList(3, 4)).flatMap(s -> s.stream()).max(Comparator.comparing(n -> n)).get());
    System.out.println("min: " + Stream.of(asList(1, 2), asList(3, 4)).flatMap(s -> s.stream()).min(Comparator.comparing(n -> n)).get());
    ----------------------------------------------------------------------
    输出:max: 4
          min: 1
    

    接收一个Comparator对象,此类提供了一个静态函数comparing可以方便用户实现一个比较器。此函数参数、返回值都是lambda表达式。返回的是一个Optional对象(后面再专门讨论),需要使用get方法获取相应的值。

    • reduce
      实现从一组值中生成一个值。前面例子中的count、max、min方法就是reduce操作,只是已经纳入了标准库中了。使用reduce实现数字累加,如下
    System.out.println("sum: " + Stream.of(1,2,3).reduce(0, (acc,elment) -> acc + elment));
    ------------------------------------
    输出:sum: 6
    

    reduce第1个参数是初始值,第二个参数叫reducer,是一个BinaryOperator类型的lambda表达式。

    参考

    《java 8函数式编程》
    http://www.importnew.com/16436.html

    相关文章

      网友评论

          本文标题:java8 lambda

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