欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > Java Lambda表达式指南

Java Lambda表达式指南

2025/4/26 22:25:12 来源:https://blog.csdn.net/qq_45351273/article/details/147403561  浏览:    关键词:Java Lambda表达式指南

一、Lambda表达式基础

1. 什么是Lambda表达式?

  • 匿名函数:没有名称的函数
  • 函数式编程:可作为参数传递的代码块
  • 简洁语法:替代匿名内部类的更紧凑写法

2. 基本语法

(parameters) -> expression
或
(parameters) -> { statements; }

3. 与传统匿名类的对比

// 传统方式
Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("Hello World");}
};// Lambda方式
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")); // 输出: HELLO

三、Lambda使用场景

1. 集合遍历

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 传统方式
for (String name : names) {System.out.println(name);
}// Lambda方式
names.forEach(name -> System.out.println(name));// 方法引用方式
names.forEach(System.out::println);

2. 线程创建

// 传统方式
new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Running in thread");}
}).start();// Lambda方式
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>() {@Overridepublic int compare(String a, String b) {return a.compareTo(b);}
});// Lambda方式
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. 流操作三阶段

  1. 创建流:集合、数组等数据源
  2. 中间操作:过滤、映射等处理
  3. 终止操作:收集、遍历等结果处理

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; // 必须是final或事实上final
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")); // 输出: 25Predicate<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)); // 输出: 8

七、异常处理

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 -> {// 可能抛出IOException的代码Files.readAllLines(Paths.get(file)).forEach(System.out::println);
}));

八、实际应用案例

1. 事件处理

// Swing按钮点击事件
JButton button = new JButton("Click");
button.addActionListener(e -> System.out.println("Button clicked"));// JavaFX事件处理
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. 方法引用优化

// 较慢 - 每次创建新Lambda
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); // 输出"Enclosing"};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) { /* ... */ }
}// 调用时会产生歧义
// calculator.calculate((x, y) -> x + y); // 编译错误

十一、Java 8+ Lambda增强

1. Java 8 - 基本Lambda支持

  • 引入函数式接口
  • 方法引用
  • Stream API

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;

十二、最佳实践

  1. 保持简洁:Lambda体最好不超过3行
  2. 使用方法引用:使代码更清晰
  3. 避免副作用:纯函数式操作更安全
  4. 命名参数:复杂Lambda应使用有意义的参数名
  5. 类型推断:通常省略参数类型,必要时显式声明
  6. 文档注释:复杂Lambda应添加注释说明

通过掌握Lambda表达式,您可以编写出更简洁、更易读的Java代码,特别是在处理集合和并发编程时。随着函数式编程在Java中的不断演进,Lambda已成为现代Java开发不可或缺的部分。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词