Lamda表達式學習筆記一 一、Lamda語法詮釋 三傻大鬧寶萊塢的主人公蘭徹說的一句話讓我映像深刻:用簡單的語言來表達同樣的意 我並不是說書上的定義怎麼怎麼不對,而是應該理解書本上的定義,並用簡單的話語描述! 那麼正題來了,lamda表達式是什麼? 定義:lamda表達式是一個可傳遞的代碼塊,可以 ...
Lamda表達式學習筆記一
一、Lamda語法詮釋
三傻大鬧寶萊塢的主人公蘭徹說的一句話讓我映像深刻:用簡單的語言來表達同樣的意
我並不是說書上的定義怎麼怎麼不對,而是應該理解書本上的定義,並用簡單的話語描述!
那麼正題來了,lamda表達式是什麼?
定義:lamda表達式是一個可傳遞的代碼塊,可以在以後執行一次或多次(將代碼像數據一樣進行傳輸)。
可傳遞的代碼塊?匿名內部類就是一種代碼塊!
1 /** 2 * 普通匿名函數 3 */ 4 @Test 5 public void test() { 6 Comparator<Integer> comparator = new Comparator<Integer>() { 7 @Override 8 public int compare(Integer x, Integer y) { 9 return Integer.compare(x, y); 10 } 11 }; 12 TreeSet<Integer> ts = new TreeSet<>(comparator); 13 } 14 15 /** 16 * lamda表達式 17 */ 18 @Test 19 public void test1() { 20 Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y); 21 TreeSet<Integer> ts = new TreeSet<>(comparator); 22 }
證明瞭lamda語法確實能代替匿名函數,也就意味著lamda表達式需要介面的支持。
需要怎麼樣的介面來支持lamda表達式呢?這個問題我們後面再說。
二、Lamda語法
分別是
- 參數列表
- lamda符號
- lamda體,介面抽象方法的實現
此處的參數列表是介面中抽象方法的形參,lamda體則是對於介面抽象方法的實現,那我們寫lamda表達式用介面中哪一個方法?這個問題,jvm是不知道的,所以我們需要的介面就是只有一個抽象方法的介面
函數式介面:只有一個抽象方法的函數,通常函數式介面用@FunctionInterface來聲明
三、lamda表達式的表現形式
lamda表達式的4種形式
-
無參->無返回值
/** * 無參->無返回值 */ @Test public void test2() { Runnable runnable = () -> System.out.println("hahahah"); runnable.run(); }View Code
2.無參->有返回值
/** * 無參->有返回值 */ @Test public void test3() { Supplier<Integer> consumer = () -> 10; Integer o = consumer.get(); System.out.println(o); }View Code
3.有參->無返回值
/** * 有參->無返回值 */ @Test public void test4() { Consumer consumer = (x) -> System.out.println(); consumer.accept("hahahah"); }View Code
4.有參-有返回值
/** * 有參->有返回值 */ @Test public void test5() { Function<Integer, Integer> function = (x) -> x * x; System.out.println(function.apply(1000)); }View Code
四、四大內置函數式介面
這四個介面分別是:Consumer<T>,Supplier<T>,Function<T, R>,Predicate<T>
1.Consumer<T> 消費型介面
@FunctionalInterface public interface Consumer<T> { void accept(T var1); default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (t) -> { this.accept(t); after.accept(t); }; } }View Code
2.Supplier<T> 供給型介面
package java.util.function; @FunctionalInterface public interface Supplier<T> { T get(); }View Code
3.Function<T, R> 功能型介面
import java.util.Objects; @FunctionalInterface public interface Function<T, R> { R apply(T var1); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (v) -> { return this.apply(before.apply(v)); }; } default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (t) -> { return after.apply(this.apply(t)); }; } static <T> Function<T, T> identity() { return (t) -> { return t; }; } }View Code
4.Predicate<T> 斷言型介面(函數返回值是boolean值)
package java.util.function; import java.util.Objects; @FunctionalInterface public interface Predicate<T> { boolean test(T var1); default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> { return this.test(t) && other.test(t); }; } default Predicate<T> negate() { return (t) -> { return !this.test(t); }; } default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> { return this.test(t) || other.test(t); }; } static <T> Predicate<T> isEqual(Object targetRef) { return null == targetRef ? Objects::isNull : (object) -> { return targetRef.equals(object); }; } static <T> Predicate<T> not(Predicate<? super T> target) { Objects.requireNonNull(target); return target.negate(); } }View Code
不僅僅有這4個函數型介面,java8還為我們提供了
最後針對lamda表達式含有3個地方可以優化
1.當只有一個參數時可以不寫小括弧
2.當lamda體中只有一條語句時可以不用加大括弧
3.參數列表可以不用聲明參數類型,jvm會根據上下文來分析數據類型(不需要考慮性能問題,因為不論如何我們的.java代碼都會進行編譯)
侵刪,文章僅供大家交流學習,第一次寫文章,有不足之處希望大家多多包涵
參考: https://www.bilibili.com/video/av62117143