新聞中心
java8之lambda表達(dá)式
目的:行為參數(shù)化
10年積累的成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有城區(qū)免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
Lambda表達(dá)式是簡(jiǎn)潔地表示可傳遞的匿名函數(shù)的一種方式:它沒(méi)有名稱,但它有參數(shù)列表、函數(shù)主體、返回類型,可能還有一個(gè)可以拋出的異常列表。
Lambda的基本語(yǔ)法是(parameters) -> expression 或 (parameters) -> { statements; }。其中, (parameters) -> expression 的表達(dá)式中隱含了return,如 () -> 42; (parameters) -> { statements; } 的花括號(hào)內(nèi)是語(yǔ)句。
舉例:
() -> 42 //參數(shù)為空,返回一個(gè)int (Listlist) -> list.isEmpty() //參數(shù)為list,返回一個(gè)boolean (int x, int y) -> x*y //參數(shù)為兩個(gè)int,返回一個(gè)int (String s) -> System.out.println(s); //參數(shù)為一個(gè)String,不返回結(jié)果 (String s) -> {System.out.println(s);} //參數(shù)為一個(gè)String,打印字符串
哪些地方使用哪些lambda
函數(shù)式接口是只定義一個(gè)抽象方法的接口,即使擁有多個(gè)默認(rèn)方法。FunctionalInterface 標(biāo)注一個(gè)函數(shù)式接口,會(huì)加入編譯檢查。函數(shù)式接口中默認(rèn)方法的目的是:改變已發(fā)布的接口而不破壞已有的實(shí)現(xiàn)。
在接受函數(shù)式接口為參數(shù)的地方,都可以使用lambda表達(dá)式。
例子:
public void execute(Runnable r){ r.run(); } execute(() -> {}); //使用lambda,Runnable是參數(shù)為空,沒(méi)有返回值的函數(shù)式接口,即() -> void //fetch返回一個(gè)函數(shù)式接口,() -> String public Callablefetch() { return () -> "Tricky example ;-)"; }
為什么只有在函數(shù)式接口的地方使用呢?lambda表達(dá)式?jīng)]有函數(shù)名,只有參數(shù)列表,函數(shù)主體和返回值,如果接口有多個(gè)方法,就不能直接匹配到正確的方法上了,所以,只有一個(gè)抽象方法的函數(shù)式接口可以滿足。
Predicate
java.util.function.Predicate
FunctionalInterface public interface Predicate{ //接口方法,入?yún)榉盒蚑,返回bool。即:(T t) -> bool boolean test(T t); //默認(rèn)方法,and操作 default Predicate and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } //默認(rèn)方法,取反操作 default Predicate negate() { return (t) -> !test(t); } //默認(rèn)方法,or 操作 default Predicate or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } //默認(rèn)方法,判斷是否相等 static Predicate isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }
使用
PredicatenonEmptyStringPredicate = (String s) -> !s.isEmpty();
Consumer
java.util.function.Consumer
@FunctionalInterface public interface Consumer{ //接口方法,入?yún)榉盒蚑,返回void。即:(T t) -> void void accept(T t); //默認(rèn)方法,可以執(zhí)行級(jí)聯(lián)操作 default Consumer andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; }
Function
java.util.function.Function
@FunctionalInterface public interface Function{ //接口方法,入?yún)榉盒蚑,返回泛型R。即:(T t) -> R R apply(T t); //默認(rèn)方法,實(shí)現(xiàn)級(jí)聯(lián)操作。before方法輸入V,輸出T,本function輸入T,輸出R。 default Function compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } //默認(rèn)方法,級(jí)聯(lián)操作 default Function andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } //默認(rèn)方法,輸入啥,輸出啥 static Function identity() { return t -> t; }
特定方法避免裝箱操作
在處理數(shù)據(jù)時(shí),使用特定方法,可以避免裝箱操作,如:IntPredicate、LongConsumer、DoubleFunction等。具體見(jiàn)API庫(kù)。
總結(jié)
函數(shù)描述符 | 函數(shù)式接口 |
---|---|
(T) ->bool | java.util.function.Predicate |
(T) -> void | java.util.function.Consumer |
(T) -> R | java.util.function.Function |
(T,U) -> R | java.util.function.BiFunction |
() -> T | java.util.function.Supplier |
只要函數(shù)描述符兼容,函數(shù)式接口就可以復(fù)用。
特殊的void兼容規(guī)則:
// Predicate返回了一個(gè)boolean Predicatep = s -> list.add(s); // Consumer返回了一個(gè)void Consumer b = s -> list.add(s);
方法引用
方法引用是調(diào)用單一方法的Lambda的快捷寫(xiě)法,格式ClassName::methodName。看下栗子你就懂了~
一般方法引用
(Apple a) -> a.getWeight() 等價(jià)于Apple::getWeight () -> Thread.currentThread().dumpStack() 等價(jià)于 Thread.currentThread()::dumpStack (str, i) -> str.substring(i) 等價(jià)于 String::substring (String s) -> System.out.println(s) 等價(jià)于 System.out::println (list, element) -> list.contains(element) 等價(jià)于 List::contains
主要有三類:
- 指向靜態(tài)方法的方法引用,如:Integer::parseInt
- 指向任意類型實(shí)例方法的方法引用,如:String::length
- 指向現(xiàn)有對(duì)象的實(shí)例方法的方法引用,如:User::getUserId
構(gòu)造函數(shù)引用
無(wú)參構(gòu)造函數(shù)
無(wú)參構(gòu)造函數(shù)的函數(shù)描述符:() -> T,由上面的總結(jié)知,可以使用Supplier接口,如下:
Supplierc1 = User::new; // c1 = () -> new User(); User user = c1.get();
有一個(gè)參數(shù)的構(gòu)造函數(shù)
有一個(gè)參數(shù)的構(gòu)造函數(shù)的函數(shù)描述符是(T) -> R,可以使用Function接口,如下:
Functionc2 = User::new; User user = c2.apply(110L);
有三個(gè)參數(shù)的構(gòu)造函數(shù)
有三個(gè)參數(shù)的構(gòu)造函數(shù)的函數(shù)描述符是(T,U,V) -> R,沒(méi)有現(xiàn)成的接口,需要自定義,如下:
@Data @AllArgsConstructor public class User { private String name; private Long userId; private Integer age; } @FunctionalInterface public interface TriFunction{ R create(T t, U u, V v); } public static void main(String[] args) { TriFunction triFunction = User::new; User user = triFunction.create("tina", 12L, 13); }
使用注意事項(xiàng)
Lambda表達(dá)式可以引用靜態(tài)變量、成員變量和最終的(final) 或事實(shí)上最終的局部變量。
更多關(guān)于java8中l(wèi)ambda表達(dá)式相關(guān)方法請(qǐng)查看下面的相關(guān)鏈接
本文題目:java8之lambda表達(dá)式用法總結(jié)
URL標(biāo)題:http://www.ef60e0e.cn/article/gicjds.html