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
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
上面的基础知识复习完毕。
如下代码应该如何理解?
@Override
public ServiceCall<NotUsed, Source<Chirp, ?>> getLiveActivityStream(String userId) {
return req -> {
return 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;
});
};
}
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>>
Lagom学习 (三)的更多相关文章
- HTTP学习三:HTTPS
HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...
- TweenMax动画库学习(三)
目录 TweenMax动画库学习(一) TweenMax动画库学习(二) TweenMax动画库学习(三) ...
- Struts2框架学习(三) 数据处理
Struts2框架学习(三) 数据处理 Struts2框架框架使用OGNL语言和值栈技术实现数据的流转处理. 值栈就相当于一个容器,用来存放数据,而OGNL是一种快速查询数据的语言. 值栈:Value ...
- 4.机器学习——统计学习三要素与最大似然估计、最大后验概率估计及L1、L2正则化
1.前言 之前我一直对于“最大似然估计”犯迷糊,今天在看了陶轻松.忆臻.nebulaf91等人的博客以及李航老师的<统计学习方法>后,豁然开朗,于是在此记下一些心得体会. “最大似然估计” ...
- DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件
DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件 本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...
- [ZZ] 深度学习三巨头之一来清华演讲了,你只需要知道这7点
深度学习三巨头之一来清华演讲了,你只需要知道这7点 http://wemedia.ifeng.com/10939074/wemedia.shtml Yann LeCun还提到了一项FAIR开发的,用于 ...
- SVG 学习<三>渐变
目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...
- Android JNI学习(三)——Java与Native相互调用
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- day91 DjangoRestFramework学习三之认证组件、权限组件、频率组件、url注册器、响应器、分页组件
DjangoRestFramework学习三之认证组件.权限组件.频率组件.url注册器.响应器.分页组件 本节目录 一 认证组件 二 权限组件 三 频率组件 四 URL注册器 五 响应器 六 分 ...
- Django基础学习三_路由系统
今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...
随机推荐
- OpenCV 中的三大数据类型( 概述 )
前言 OpenCV 提供了许多封装好了的类型,而其中,以三大类型最为核心.本文将大致介绍这三大类型. CvArr:不确定数组 它可以被视为一个抽象基类,后面的两大类型都继承此类型并扩展.只要某个函数的 ...
- spirng boot资料
这里有个srping boot 各种整合的资料 https://blog.csdn.net/Winter_chen001/article/details/80537829 SpringBoot入门总结 ...
- android菜鸟学习笔记5----第一个android程序
程序功能:点击一个按钮,然后弹出一个提示信息 Step 1:在eclipse中新建一个android application project,在创建过程中不勾选create activity,这样就创 ...
- js实现网页中的"运行代码"功能
<!DOCTYPE html> <html> <head> <meta charset='utf8' /> <title>网页中的运行代码功 ...
- 深入了解Cookie(1)------selenium2进行Cookie操作的前奏
世界上最宽阔的是海洋,比海洋还宽阔的是天空,比天空还宽阔的是人的心量.做人的心量有多大.人生的成就就有多大. 不为一己之利去争.去斗.去夺,扫除报复之心和妒忌之念.自然"心底无私天地宽&qu ...
- WordPress用户角色及其权限管理编辑插件:User Role Editor汉化版
如果Wordpress默认的用户角色及权限不能满足您的需求,又觉得修改代码编辑用户权限太麻烦.那不妨试试User Role Editor,Wordpress用户角色及其权限管理编辑插件. User R ...
- Nginx + Tomcat 应用证书启用 SSL
第一部分 简述 - 附:相关概念 1 Nginx 是什么? - 2 Tomcat 是什么? - 3 SSL 是什么? Secure Sockets Layer,现在应该叫"TLS" ...
- Java for LeetCode 130 Surrounded Regions
Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...
- Numpy数组的保存与读取方法
1. 数组以二进制格式保存 np.save和np.load是读写磁盘数组数据的两个主要函数.默认情况下,数组以未压缩的原始二进制格式保存在扩展名为npy的文件中,以数组a为例 np.save(&quo ...
- Java一致性的实现
一致性 内存模型 每一个线程有一个工作内存和主存独立 工作内存存放主存中变量的值的拷贝 Happen Before 1.程序次序规则:在一个单独的线程中,按照程序代码的执行流顺序,(时 ...