Lambda基本:https://blog.csdn.net/wargon/article/details/80656575
https://www.cnblogs.com/hyyq/p/7425666.html
四大核心函數式編程接口:
https://blog.csdn.net/a879611951/article/details/80104014
https://blog.csdn.net/chuji2012/article/details/77871011
函數式編程教程(阮一峰):
http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html
Function接口結合Lambda表達式實現:
https://blog.csdn.net/huo065000/article/details/78964382
https://segmentfault.com/a/1190000012248864
Stream,方法引用和this:
https://www.cnblogs.com/aoeiuv/p/5911692.html
https://blog.csdn.net/blacksoil55/article/details/78359045
四大函數式編程接口的意義在於,普通類方法在定義以它們作為函數式的參數后,可以在類方法中直接調用它們的apply,consume等方法,傳入參數,獲取結果等,返回。在調用普通類方法時,傳入lamda表達式作為這些函數式編程接口的實例,就是實現了apply,consume,test這些(唯一)抽象方法。這些方法有的接收入參返回出參,有的不返回,有的無入參,有的返回boolean等。注意應用lamda表達式的特性,如果是一句話表達式,表達式結果即函數式接口的抽象方法返回值;多行需要加{}且每句加分號。
如果不用這些函數式接口,我們就需要自己先定義一個函數式編程接口(詳見lamda表達式入門),再定義普通類方法以我們自定義的函數式接口為參數,在類方法中調用函數式接口方法。然后在類方法調用時傳入lamda表達式。
例子:
authorityList.stream().filter(authority ->
!StrUtil.equals(authority.getAuthority(), "ROLE_USER"))
.forEach(authority -> {
Set<MenuVO> menuVOSet = menuService.findMenuByRole(authority.getAuthority());
CollUtil.addAll(urls, menuVOSet);
});
其中filter的參數是Predicate函數式接口:
Stream<T> filter(Predicate<? super T> predicate);
filter這個普通類方法的一個實現為:
@Override
public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
Objects.requireNonNull(predicate);
return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
}
@Override
public void accept(P_OUT u) {
if (predicate.test(u))
downstream.accept(u);
}
};
}
};
}
里面就調用了Predicate函數式接口的test方法。
對filter這個普通類方法的實際調用為:
authorityList.stream().filter(authority ->
!StrUtil.equals(authority.getAuthority(), "ROLE_USER"))
也就是傳入了lamda表達式,作為Predicate接口的實現,其中的
!StrUtil.equals(authority.getAuthority(), "ROLE_USER")
就是Predicate接口的test方法的實現,接收了authority 作為參數,省略了return,返回的就是表達式執行結果,一個boolean類型值。
關於Stream,Optional接口的例子:
urls.stream().filter(menu -> StrUtil.isNotEmpty(menu.getUrl())
&& antPathMatcher.match(menu.getUrl(), request.getRequestURI())
&& request.getMethod().equalsIgnoreCase(menu.getMethod()))
.findFirst().ifPresent(menuVO -> hasPermission.set(true));
這里stream和filter方法(filter方法語義原理見上文分析)均返回Stream,代表Collection容器的元素流對象,findFirst返回Optional,代表包裝的可能存在的流元素,其中的value代表Collection中的實際元素值。
ifPresent方法定義為:
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
可見這里的語義是判斷Collection中第一個元素是否非空,非空則執行Consumer接口的lamda表達式,將一個權限標識設置為true(判斷這個權限標識來決定該用戶是否有權限訪問該鏈接)