zoukankan      html  css  js  c++  java
  • Lagom学习 (三)

    lagom代码中有大量的Lambda表达式,首先补习一下lambda表达式和函数式接口的相关知识。

    一: 函数式接口

    • 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:

                      这种类型的接口,使得以其为参数的方法,可以在调用时,使用一个lambda表达式作为参数(比如new Thread(Runable), 中的参数)。

                       从另一个方面说,一旦我们调用某方法,可以传入lambda表达式作为参数,则这个方法的参数类型,必定是一个函数式的接口。

    • 什么是函数式接口:

                       接口用@FunctionalInterface注解修饰,但不是必须的;

                       这个接口中,只能有一个函数需要被实现;

                       但是可以有默认方法(default修饰)与静态方法(static修饰,并可以提供static方式实现);

                       可以有 Object 中覆盖的方法,也就是 equals,toString,hashcode等方法。

    • 注意:

             FunctionalInterface注解标注一个函数式接口,不能标注方法枚举属性这些。

          如果接口被标注了@FunctionalInterface,这个类就必须符合函数式接口的规范

          即使一个接口没有标注@FunctionalInterface,如果这个接口满足函数式接口规则,依旧被当作函数式接口。

    Runnable接口就是一个函数式接口:

    @FunctionalInterface
    public interface Runnable {
        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }

    可以自定义函数式接口:

    这个接口由一个需要实现的函数,这个函数的参数是F,返回的是T;

    @FunctionalInterface
    interface Converter<F, T> {
        T convert(F from);
    }

    使用: 如下的lambda表达式(from) -> Integer.valueOf(from);  这个表达式的格式要和上面的函数匹配,也就是说F在这里是String类型,T是Integer类型,from就是F,Integer.valueof(from)的结果是integer,T就是integer;

    Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
    Integer converted = converter.convert("123");

    如下为一些已经实现的函数式接口:

     // Function<T, R> -T作为输入,返回的R作为输出
        Function<String,String> function = (x) -> {System.out.print(x+": ");return "Function";};
        System.out.println(function.apply("hello world"));
     //Predicate<T> -T作为输入,返回的boolean值作为输出
        Predicate<String> pre = (x) ->{System.out.print(x);return false;};
        System.out.println(": "+pre.test("hello World"));
     //Consumer<T> - T作为输入,执行某种动作但没有返回值
        Consumer<String> con = (x) -> {System.out.println(x);};
        con.accept("hello world");
     //Supplier<T> - 没有任何输入,返回T
        Supplier<String> supp = () -> {return "Supplier";};
        System.out.println(supp.get());
     //BinaryOperator<T> -两个T作为输入,返回一个T作为输出,对于“reduce”操作很有用
        BinaryOperator<String> bina = (x,y) ->{System.out.print(x+" "+y);return "BinaryOperator";};
        System.out.println("  "+bina.apply("hello ","world"));

    这里以Function接口为例:

      Function接口的需要实现的函数是"R apply(T t)", 参数是t, 返回值是R;
      Function<String,String> function = (x) -> {System.out.print(x+": ");return "Function";}; 这里的T是String类型,R也是String类型;
      System.out.println(function.apply("hello world")); // Function.apply()返回的是String类型,满足System.out.println的参数需要;“hello world”
    是String类型,也满足apply的参数需要。
    /*
     * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     */
    package java.util.function;
    import java.util.Objects;
    /**
     * Represents a function that accepts one argument and produces a result.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #apply(Object)}.
     *
     * @param <T> the type of the input to the function
     * @param <R> the type of the result of the function
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Function<T, R> {
        /**
         * Applies this function to the given argument.
         *
         * @param t the function argument
         * @return the function result
         */
        R apply(T t);
    
        /**
         * Returns a composed function that first applies the {@code before}
         * function to its input, and then applies this function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of input to the {@code before} function, and to the
         *           composed function
         * @param before the function to apply before this function is applied
         * @return a composed function that first applies the {@code before}
         * function and then applies this function
         * @throws NullPointerException if before is null
         *
         * @see #andThen(Function)
         */
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        /**
         * Returns a composed function that first applies this function to
         * its input, and then applies the {@code after} function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of output of the {@code after} function, and of the
         *           composed function
         * @param after the function to apply after this function is applied
         * @return a composed function that first applies this function and then
         * applies the {@code after} function
         * @throws NullPointerException if after is null
         *
         * @see #compose(Function)
         */
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    
        /**
         * Returns a function that always returns its input argument.
         *
         * @param <T> the type of the input and output objects to the function
         * @return a function that always returns its input argument
         */
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }

    Lambda表达式

    书写方法:  e -> System.out.println( e )

        1. 三部分构成

            参数列表

            符号 ->

            函数体 : 有多个语句,可以用{} 包括, 如果需要返回值且只有一个语句,可以省略 return

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    上面的基础知识复习完毕。

    如下代码应该如何理解?

     1  @Override
     2   public ServiceCall<NotUsed, Source<Chirp, ?>> getLiveActivityStream(String userId) {
     3     return req -> {
     4       return friendService.getUser(userId).invoke().thenCompose(user -> {
     5         PSequence<String> userIds = user.friends.plus(userId);
     6         LiveChirpsRequest chirpsReq =  new LiveChirpsRequest(userIds);
     7         // Note that this stream will not include changes to friend associates,
     8         // e.g. adding a new friend.
     9         CompletionStage<Source<Chirp, ?>> result = chirpService.getLiveChirps().invoke(chirpsReq);
    10         return result;
    11       });
    12     };
    13   }
    ServiceCall是一个函数式接口,其函数是invoke,invoke参数是Request,返回的是CompletionStage<Response>, getLiveActivityStream需要返回ServiceCall接口,因为
    其是函数式,所以可以返回 "CompletionStage<Response> invoke(Request var1)",line 3 ~ line 12参数是Request,返回CompletionStage<Response>,满足函数
    的定义要求。
    
    
    @FunctionalInterface
    public interface ServiceCall<Request, Response> {
        CompletionStage<Response> invoke(Request var1);
    ...
    }
    再看如下代码:
    friendService.getUser(userId)返回的类型是ServiceCall接口,invoke是接口函数,而friendService.getUser的实现里面返回的就是一个lambad表达式,
    friendService.getUser(userId).invoke()就会执行friendService.getUser中实现的代码。
    friendService.getUser(userId).invoke().thenCompose(user -> {
      PSequence<String> userIds = user.friends.plus(userId);
      LiveChirpsRequest chirpsReq =  new LiveChirpsRequest(userIds);
      // Note that this stream will not include changes to friend associates,
      // e.g. adding a new friend.
      CompletionStage<Source<Chirp, ?>> result = chirpService.getLiveChirps().invoke(chirpsReq);
      return result;
    });
    invoke()函数返回的是CompletionStage<Response>,不是一个函数式接口,那么调用其thenCompose方法,参数类型是fn,
    public <U> CompletionStage<U> thenCompose
    (Function<? super T, ? extends CompletionStage<U>> fn);

    user就是? super T, 返回的CompletionStage<Source<Chirp, ?>> 就是 ? extends CompletionStage<U>>


    
    
    
  • 相关阅读:
    自己改了个{svn服务器端绿色版}
    Android去掉顶部的阴影
    SqliteOpenHelper的onUpgrade()死活不运行的解法
    前端模拟发送数据/调试的好工具:Chrome下的PostmanREST Client
    mouseenter & mouseleave VS mouseover & mouseout
    Android WindowManager$BadTokenException异常应对案例
    Eclipse快捷键大全(转载)
    360桌面JSAPI一个诡异的bug:客户端与网页通过js通信
    《你在哪》1.34强势发布,新增“图片墙”
    经过一个月的奋斗,我的第一个Android作品《麦芒》诞生了
  • 原文地址:https://www.cnblogs.com/liufei1983/p/8445085.html
Copyright © 2011-2022 走看看