Lambda 表达式
Lambda表达式是Java 8引入的一个重要特性,它提供了一种简洁的方式来表示匿名函数。
Lambda表达式的语法
Lambda表达式的基本语法是:(parameters) -> expression 或 (parameters) -> { statements; }
| 语法形式 | 示例 | 说明 |
|---|
| 无参数 | () -> System.out.println("Hello") | 无参数的Lambda表达式 |
| 单个参数 | x -> x + 1 | 单个参数可省略括号 |
| 多个参数 | (x, y) -> x + y | 多个参数需要用括号 |
| 有类型声明 | (int x, int y) -> x + y | 带类型声明的参数 |
| 多条语句 | (x, y) -> { int sum = x + y; return sum; } | 多条语句需要用花括号 |
Lambda表达式示例
public class LambdaExample { public static void basicLambdaExamples() { // 无参Lambda Runnable runnable = () -> System.out.println("Hello from Lambda!"); runnable.run(); // 单参Lambda Function<String, Integer> stringToInt = s -> s.length(); System.out.println("Length: " + stringToInt.apply("Hello")); // 多参Lambda BinaryOperator<Integer> add = (x, y) -> x + y; System.out.println("Sum: " + add.apply(5, 3)); // 带类型声明的Lambda BinaryOperator<Integer> multiply = (Integer x, Integer y) -> x * y; System.out.println("Product: " + multiply.apply(4, 6)); // 多语句Lambda Function<Integer, String> processNumber = (Integer num) -> { if (num > 0) { return "Positive: " + num; } else if (num < 0) { return "Negative: " + num; } else { return "Zero"; } }; System.out.println(processNumber.apply(-5)); } // Lambda与集合操作 public static void lambdaWithCollections() { List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // 使用Lambda表达式遍历集合 names.forEach(name -> System.out.println(name)); // 使用方法引用(Method Reference) names.forEach(System.out::println); // 使用Lambda过滤 names.stream() .filter(name -> name.startsWith("A")) .forEach(System.out::println); }}
Stream API
Stream API是Java 8引入的另一个重要特性,提供了函数式编程的能力,可以对集合进行各种操作。
Stream操作类型
| 操作类型 | 说明 | 示例 |
|---|
| 中间操作 | 返回Stream,可以链式调用 | filter, map, sorted, distinct |
| 终端操作 | 返回结果或副作用,结束Stream | collect, forEach, reduce, count |
Stream常用方法
| 方法 | 说明 | 示例 |
|---|
filter(Predicate<T>) | 过滤元素 | stream.filter(x -> x > 5) |
map(Function<T,R>) | 转换元素 | stream.map(String::length) |
flatMap(Function<T,Stream<R>>) | 扁平化映射 | stream.flatMap(list -> list.stream()) |
distinct() | 去重 | stream.distinct() |
sorted() | 排序 | stream.sorted() |
limit(long n) | 限制元素数量 | stream.limit(5) |
skip(long n) | 跳过元素 | stream.skip(2) |
forEach(Consumer<T>) | 遍历 | stream.forEach(System.out::println) |
collect(Collectors) | 收集结果 | stream.collect(Collectors.toList()) |
reduce(BinaryOperator<T>) | 归约操作 | stream.reduce(Integer::sum) |
count() | 计数 | stream.count() |
findFirst() | 获取第一个元素 | stream.findFirst() |
anyMatch(Predicate<T>) | 是否任意匹配 | stream.anyMatch(x -> x > 10) |
allMatch(Predicate<T>) | 是否全部匹配 | stream.allMatch(x -> x > 0) |
noneMatch(Predicate<T>) | 是否都不匹配 | stream.noneMatch(x -> x < 0) |
Stream API 示例
public static void basicStreamOperations() { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 过滤偶数并求平方 List<Integer> evenSquares = numbers.stream() .filter(n -> n % 2 == 0) // 过滤偶数 .map(n -> n * n) // 求平方 .collect(Collectors.toList()); // 收集结果 System.out.println("Even squares: " + evenSquares); // 字符串操作示例 List<String> words = Arrays.asList("hello", "world", "java", "stream", "api"); List<String> upperWords = words.stream() .filter(word -> word.length() > 4) // 过滤长度大于4的单词 .map(String::toUpperCase) // 转大写 .sorted() // 排序 .collect(Collectors.toList()); System.out.println("Filtered and transformed words: " + upperWords); // 数字流操作 int sum = IntStream.rangeClosed(1, 100) .filter(n -> n % 2 == 0) // 偶数 .sum(); // 求和 System.out.println("Sum of even numbers 1-100: " + sum);}public static void advancedStreamOperations() { List<Person> people = Arrays.asList( new Person("Alice", 25, "Engineer"), new Person("Bob", 30, "Designer"), new Person("Charlie", 35, "Engineer"), new Person("David", 28, "Manager"), new Person("Eve", 32, "Engineer") ); // 按职业分组 Map<String, List<Person>> groupedByJob = people.stream() .collect(Collectors.groupingBy(Person::getJob)); System.out.println("Grouped by job: " + groupedByJob); // 按年龄统计 IntSummaryStatistics ageStats = people.stream() .mapToInt(Person::getAge) .summaryStatistics(); System.out.println("Age statistics: " + ageStats); // 查找特定条件的元素 Optional<Person> engineer = people.stream() .filter(p -> p.getJob().equals("Engineer")) .findFirst(); engineer.ifPresent(p -> System.out.println("First engineer: " + p.getName())); // 字符串连接 String names = people.stream() .map(Person::getName) .collect(Collectors.joining(", ")); System.out.println("Names joined: " + names);}// 并行流示例public static void parallelStreamExample() { List<Integer> numbers = IntStream.rangeClosed(1, 1000000) .boxed() .collect(Collectors.toList()); // 串行流 long startTime = System.currentTimeMillis(); long serialSum = numbers.stream() .mapToLong(Long::valueOf) .sum(); long serialTime = System.currentTimeMillis() - startTime; // 并行流 startTime = System.currentTimeMillis(); long parallelSum = numbers.parallelStream() .mapToLong(Long::valueOf) .sum(); long parallelTime = System.currentTimeMillis() - startTime; System.out.println("Serial sum: " + serialSum + ", time: " + serialTime + "ms"); System.out.println("Parallel sum: " + parallelSum + ", time: " + parallelTime + "ms");}// 内部类用于示例static class Person { private String name; private int age; private String job; public Person(String name, int age, String job) { this.name = name; this.age = age; this.job = job; } // getter方法 public String getName() { return name; } public int getAge() { return age; } public String getJob() { return job; } @Override public String toString() { return String.format("Person{name='%s', age=%d, job='%s'}", name, age, job); } }}
Optional 类
Optional是Java 8引入的容器类,用于解决空指针异常问题。
Optional常用方法
| 方法 | 说明 | 示例 |
|---|
Optional.empty() | 创建空Optional | Optional<String> opt = Optional.empty(); |
Optional.of(value) | 创建非空Optional | Optional<String> opt = Optional.of("Hello"); |
Optional.ofNullable(value) | 创建可能为空的Optional | Optional<String> opt = Optional.ofNullable(str); |
isPresent() | 检查是否有值 | opt.isPresent() |
isEmpty() | 检查是否为空 | opt.isEmpty() (Java 11+) |
get() | 获取值(不安全) | opt.get() |
orElse(defaultValue) | 获取值或默认值 | opt.orElse("Default") |
orElseGet(Supplier) | 惰性获取默认值 | opt.orElseGet(() -> computeDefault()) |
orElseThrow() | 无值时抛异常 | opt.orElseThrow() |
orElseThrow(Supplier) | 无值时抛指定异常 | opt.orElseThrow(() -> new CustomException()) |
ifPresent(Consumer) | 有值时执行 | opt.ifPresent(System.out::println) |
ifPresentOrElse(Consumer, Runnable) | 有值/无值分别处理 | opt.ifPresentOrElse(...) (Java 9+) |
filter(Predicate) | 过滤 | opt.filter(s -> s.length() > 5) |
map(Function) | 转换 | opt.map(String::length) |
flatMap(Function) | 扁平化转换 | opt.flatMap(this::processString) |
Optional示例
public class OptionalExample { public static void basicOptionalOperations() { // 创建Optional的不同方式 Optional<String> emptyOpt = Optional.empty(); Optional<String> nonEmptyOpt = Optional.of("Hello"); Optional<String> nullableOpt = Optional.ofNullable(null); // 检查值是否存在 System.out.println("Empty opt present: " + emptyOpt.isPresent()); System.out.println("Non-empty opt present: " + nonEmptyOpt.isPresent()); // 获取值或默认值 String value1 = emptyOpt.orElse("Default Value"); String value2 = nonEmptyOpt.orElse("Default Value"); System.out.println("Value from empty opt: " + value1); System.out.println("Value from non-empty opt: " + value2); // 使用ifPresent处理值 nonEmptyOpt.ifPresent(s -> System.out.println("Got value: " + s)); // 使用map转换值 Optional<Integer> lengthOpt = nonEmptyOpt.map(String::length); lengthOpt.ifPresent(len -> System.out.println("Length: " + len)); // 使用filter过滤 Optional<String> filteredOpt = nonEmptyOpt .filter(s -> s.length() > 10) .map(String::toUpperCase); System.out.println("Filtered result: " + filteredOpt.orElse("Not found")); } // Optional在实际业务中的应用 public static void practicalOptionalUsage() { UserService userService = new UserService(); // 传统方式(容易出现NPE) User user1 = userService.findById(1L); if (user1 != null) { Profile profile = user1.getProfile(); if (profile != null) { Address address = profile.getAddress(); if (address != null) { System.out.println("Address: " + address.getCity()); } } } // 使用Optional的优雅方式 Optional.ofNullable(userService.findById(1L)) .map(User::getProfile) .map(Profile::getAddress) .map(Address::getCity) .ifPresent(city -> System.out.println("Address: " + city)); // 处理可能的异常情况 String result = Optional.ofNullable(userService.findById(999L)) .map(User::getProfile) .map(Profile::getEmail) .orElse("No email found"); System.out.println("Email result: " + result); } // 内部类用于示例 static class UserService { public User findById(Long id) { if (id == 1L) { return new User("John Doe", new Profile("john@example.com", new Address("New York"))); } return null; } } static class User { private String name; private Profile profile; public User(String name, Profile profile) { this.name = name; this.profile = profile; } public Profile getProfile() { return profile; } } static class Profile { private String email; private Address address; public Profile(String email, Address address) { this.email = email; this.address = address; } public String getEmail() { return email; } public Address getAddress() { return address; } } static class Address { private String city; public Address(String city) { this.city = city; } public String getCity() { return city; } }}
函数式接口
函数式接口是只有一个抽象方法的接口,可以被Lambda表达式实现。
常用函数式接口
| 接口 | 抽象方法 | 用途 | 示例 |
|---|
Predicate<T> | boolean test(T t) | 断言,返回boolean | x -> x > 5 |
Function<T,R> | R apply(T t) | 转换,接收T返回R | x -> x * 2 |
Consumer<T> | void accept(T t) | 消费,接收T不返回 | x -> System.out.println(x) |
Supplier<T> | T get() | 供应,不接收返回T | () -> new Object() |
UnaryOperator<T> | T apply(T t) | 一元操作,T->T | x -> x.toUpperCase() |
BinaryOperator<T> | T apply(T t1, T t2) | 二元操作,(T,T)->T | (x, y) -> x + y |
BiFunction<T,U,R> | R apply(T t, U u) | 二元函数,(T,U)->R | (x, y) -> x + y |
BiConsumer<T,U> | void accept(T t, U u) | 二元消费,(T,U) | (x, y) -> System.out.println(x + y) |
自定义函数式接口
@FunctionalInterfacepublic interface Calculator { int calculate(int a, int b);// 可以有默认方法default void printResult(int result) { System.out.println("Result: " + result);}// 可以有静态方法static Calculator getAdditionCalculator() { return (a, b) -> a + b; }} public class FunctionalInterfaceExample { public static void demonstrateCustomFunctionalInterface() { Calculator addition = (a, b) -> a + b; Calculator multiplication = (a, b) -> a * b; int addResult = addition.calculate(5, 3); int multResult = multiplication.calculate(5, 3); addition.printResult(addResult); multiplication.printResult(multResult); Calculator defaultCalc = Calculator.getAdditionCalculator(); defaultCalc.printResult(defaultCalc.calculate(10, 20)); }}