一、Lambda表達式基礎
1. 什么是Lambda表達式?
匿名函數 :沒有名稱的函數函數式編程 :可作為參數傳遞的代碼塊簡潔語法 :替代匿名內部類的更緊湊寫法
2. 基本語法
( parameters) -> expression
或
( parameters) -> { statements; }
3. 與傳統匿名類的對比
Runnable r1 = new Runnable ( ) { @Override public void run ( ) { System . out. println ( "Hello World" ) ; }
} ;
Runnable r2 = ( ) -> System . out. println ( "Hello World" ) ;
二、函數式接口
1. 什么是函數式接口?
單抽象方法接口 :只有一個抽象方法的接口可用@FunctionalInterface
注解標記
2. Java內置核心函數式接口
接口 方法 用途 Supplier<T>
T get()
無參返回結果 Consumer<T>
void accept(T t)
接收單個參數無返回 Function<T,R>
R apply(T t)
接收T類型返回R類型 Predicate<T>
boolean test(T t)
接收T返回布爾值 UnaryOperator<T>
T apply(T t)
一元操作(同類型轉換) BiFunction<T,U,R>
R apply(T t, U u)
接收T,U返回R
3. 自定義函數式接口
@FunctionalInterface
interface StringProcessor { String process ( String input) ; default void info ( ) { System . out. println ( "String processing interface" ) ; }
} StringProcessor toUpper = s -> s. toUpperCase ( ) ;
System . out. println ( toUpper. process ( "hello" ) ) ;
三、Lambda使用場景
1. 集合遍歷
List < String > names = Arrays . asList ( "Alice" , "Bob" , "Charlie" ) ;
for ( String name : names) { System . out. println ( name) ;
}
names. forEach ( name -> System . out. println ( name) ) ;
names. forEach ( System . out:: println ) ;
2. 線程創建
new Thread ( new Runnable ( ) { @Override public void run ( ) { System . out. println ( "Running in thread" ) ; }
} ) . start ( ) ;
new Thread ( ( ) -> System . out. println ( "Running in thread" ) ) . start ( ) ;
3. 條件過濾
List < Integer > numbers = Arrays . asList ( 1 , 2 , 3 , 4 , 5 , 6 ) ;
List < Integer > evens = numbers. stream ( ) . filter ( n -> n % 2 == 0 ) . collect ( Collectors . toList ( ) ) ;
4. 排序
List < String > words = Arrays . asList ( "banana" , "apple" , "pear" ) ;
Collections . sort ( words, new Comparator < String > ( ) { @Override public int compare ( String a, String b) { return a. compareTo ( b) ; }
} ) ;
Collections . sort ( words, ( a, b) -> a. compareTo ( b) ) ;
words. sort ( Comparator . naturalOrder ( ) ) ;
四、方法引用
1. 四種方法引用類型
類型 語法 對應的Lambda 靜態方法 ClassName::staticMethod
(args) -> ClassName.staticMethod(args)
實例方法 instance::method
(args) -> instance.method(args)
任意對象的實例方法 ClassName::method
(obj, args) -> obj.method(args)
構造方法 ClassName::new
(args) -> new ClassName(args)
2. 使用示例
Function < String , Integer > parser = Integer :: parseInt ;
String str = "Hello" ;
Supplier < Integer > lengthSupplier = str:: length ;
Function < String , String > upperCase = String :: toUpperCase ;
Supplier < List < String > > listSupplier = ArrayList :: new ;
五、Stream API與Lambda
1. 流操作三階段
創建流 :集合、數組等數據源中間操作 :過濾、映射等處理終止操作 :收集、遍歷等結果處理
2. 常用流操作
List < String > names = Arrays . asList ( "Alice" , "Bob" , "Charlie" , "David" ) ;
List < String > longNames = names. stream ( ) . filter ( name -> name. length ( ) > 4 ) . collect ( Collectors . toList ( ) ) ;
List < Integer > nameLengths = names. stream ( ) . map ( String :: length ) . collect ( Collectors . toList ( ) ) ;
List < String > sorted = names. stream ( ) . sorted ( ( a, b) -> b. compareTo ( a) ) . collect ( Collectors . toList ( ) ) ;
Optional < String > longest = names. stream ( ) . max ( Comparator . comparingInt ( String :: length ) ) ;
3. 并行流
long count = names. parallelStream ( ) . filter ( name -> name. length ( ) > 4 ) . count ( ) ;
六、Lambda高級特性
1. 變量捕獲
int threshold = 5 ;
List < Integer > numbers = Arrays . asList ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ) ; List < Integer > aboveThreshold = numbers. stream ( ) . filter ( n -> n > threshold) . collect ( Collectors . toList ( ) ) ;
2. 組合函數
Function < String , Integer > strToInt = Integer :: parseInt ;
Function < Integer , Integer > square = n -> n * n; Function < String , Integer > squareOfNumber = strToInt. andThen ( square) ;
System . out. println ( squareOfNumber. apply ( "5" ) ) ; Predicate < String > isLong = s -> s. length ( ) > 10 ;
Predicate < String > containsA = s -> s. contains ( "a" ) ;
Predicate < String > longAndContainsA = isLong. and ( containsA) ;
3. 閉包示例
Function < Integer , Function < Integer , Integer > > adder = x -> y -> x + y;
Function < Integer , Integer > add5 = adder. apply ( 5 ) ;
System . out. println ( add5. apply ( 3 ) ) ;
七、異常處理
1. Lambda中的異常處理
List < String > numbers = Arrays . asList ( "1" , "2" , "three" , "4" ) ; numbers. forEach ( s -> { try { System . out. println ( Integer . parseInt ( s) ) ; } catch ( NumberFormatException e) { System . out. println ( "Invalid number: " + s) ; }
} ) ;
2. 編寫可拋出異常的Lambda
@FunctionalInterface
interface ThrowingConsumer < T , E extends Exception > { void accept ( T t) throws E ;
} static < T > Consumer < T > wrap ( ThrowingConsumer < T , Exception > consumer) { return t -> { try { consumer. accept ( t) ; } catch ( Exception e) { throw new RuntimeException ( e) ; } } ;
}
List < String > files = Arrays . asList ( "file1.txt" , "file2.txt" ) ;
files. forEach ( wrap ( file -> { Files . readAllLines ( Paths . get ( file) ) . forEach ( System . out:: println ) ;
} ) ) ;
八、實際應用案例
1. 事件處理
JButton button = new JButton ( "Click" ) ;
button. addActionListener ( e -> System . out. println ( "Button clicked" ) ) ;
Button fxButton = new Button ( "Click" ) ;
fxButton. setOnAction ( event -> System . out. println ( "FX Button clicked" ) ) ;
2. 緩存模式
public class Cache < K , V > { private final Map < K , V > map = new HashMap < > ( ) ; private final Function < K , V > loader; public Cache ( Function < K , V > loader) { this . loader = loader; } public V get ( K key) { return map. computeIfAbsent ( key, loader) ; }
}
Cache < String , BigDecimal > priceCache = new Cache < > ( productId -> fetchPriceFromDatabase ( productId) ) ;
BigDecimal price = priceCache. get ( "P1001" ) ;
3. 策略模式
interface PaymentStrategy { void pay ( BigDecimal amount) ;
} class PaymentProcessor { private PaymentStrategy strategy; public void setStrategy ( PaymentStrategy strategy) { this . strategy = strategy; } public void processPayment ( BigDecimal amount) { strategy. pay ( amount) ; }
}
PaymentProcessor processor = new PaymentProcessor ( ) ;
processor. setStrategy ( amount -> System . out. println ( "Paying " + amount + " via Credit Card" ) ) ;
processor. processPayment ( new BigDecimal ( "100.00" ) ) ;
processor. setStrategy ( amount -> System . out. println ( "Paying " + amount + " via Alipay" ) ) ;
processor. processPayment ( new BigDecimal ( "200.00" ) ) ;
九、性能考慮
1. Lambda vs 匿名類
初始化性能 :Lambda首次調用稍慢,后續調用更快內存占用 :Lambda通常占用更少內存最佳實踐 :在熱點代碼中避免頻繁創建Lambda
2. 方法引用優化
list. stream ( ) . map ( x -> x. toString ( ) ) . collect ( Collectors . toList ( ) ) ;
list. stream ( ) . map ( Object :: toString ) . collect ( Collectors . toList ( ) ) ;
3. 并行流注意事項
數據量小(<1000元素)時順序流更快 確保操作是無狀態的 避免共享可變狀態
十、常見問題與陷阱
1. 變量修改
int sum = 0 ;
numbers. forEach ( n -> { sum += n;
} ) ;
int [ ] sumHolder = { 0 } ;
numbers. forEach ( n -> sumHolder[ 0 ] += n) ;
2. this關鍵字
public class LambdaThis { private String value = "Enclosing" ; public void doWork ( ) { Runnable r = ( ) -> { System . out. println ( this . value) ; } ; r. run ( ) ; }
}
3. 重載問題
interface Adder { int add ( int a, int b) ;
} interface SmartAdder { int add ( double a, double b) ;
} class Calculator { void calculate ( Adder adder) { } void calculate ( SmartAdder adder) { }
}
十一、Java 8+ Lambda增強
1. Java 8 - 基本Lambda支持
2. Java 11 - 局部變量語法
var list = List . of ( "a" , "b" , "c" ) ;
list. forEach ( ( var s) -> System . out. println ( s) ) ;
3. Java 17 - 密封接口
sealed interface MathOperation permits Add , Subtract { int operate ( int a, int b) ;
} final class Add implements MathOperation { public int operate ( int a, int b) { return a + b; }
} final class Subtract implements MathOperation { public int operate ( int a, int b) { return a - b; }
}
MathOperation add = ( a, b) -> a + b;
十二、最佳實踐
保持簡潔 :Lambda體最好不超過3行使用方法引用 :使代碼更清晰避免副作用 :純函數式操作更安全命名參數 :復雜Lambda應使用有意義的參數名類型推斷 :通常省略參數類型,必要時顯式聲明文檔注釋 :復雜Lambda應添加注釋說明
通過掌握Lambda表達式,您可以編寫出更簡潔、更易讀的Java代碼,特別是在處理集合和并發編程時。隨著函數式編程在Java中的不斷演進,Lambda已成為現代Java開發不可或缺的部分。