十、Lambda表达式
10.1 Lambda基础
public class LambdaDemo {
// 函数式接口
@FunctionalInterface
interface StringOperation {
String operate(String s);
}
@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}
public void demo() {
// 传统匿名内部类
MathOperation addOld = new MathOperation() {
@Override
public int operate(int a, int b) {
return a + b;
}
};
// Lambda表达式
MathOperation add = (a, b) -> a + b;
MathOperation subtract = (a, b) -> a - b;
MathOperation multiply = (a, b) -> a * b;
// 带代码块的Lambda
MathOperation divide = (a, b) -> {
if (b == 0) {
throw new ArithmeticException("除数不能为0");
}
return a / b;
};
// 单参数Lambda(可省略括号)
StringOperation toUpper = s -> s.toUpperCase();
StringOperation toLower = String::toLowerCase; // 方法引用
// 使用Lambda
System.out.println(calculate(10, 5, add)); // 15
System.out.println(calculate(10, 5, subtract)); // 5
System.out.println(calculate(10, 5, multiply)); // 50
}
private int calculate(int a, int b, MathOperation op) {
return op.operate(a, b);
}
}
10.2 方法引用
public class MethodReferenceDemo {
// 方法引用的四种形式
// 1. 静态方法引用:Class::staticMethod
public void staticRef() {
// Lambda形式
Function<String, Integer> lambda = s -> Integer.parseInt(s);
// 方法引用形式
Function<String, Integer> ref = Integer::parseInt;
// 使用
Integer num = ref.apply("123");
}
// 2. 实例方法引用:instance::method
public void instanceRef() {
List<String> list = Arrays.asList("a", "b", "c");
// Lambda形式
list.forEach(s -> System.out.println(s));
// 方法引用形式
list.forEach(System.out::println);
}
// 3. 特定类型实例方法引用:Class::method
public void specificTypeRef() {
List<String> list = Arrays.asList("hello", "world");
// Lambda形式
list.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
// 方法引用形式
list.sort(String::compareToIgnoreCase);
}
// 4. 构造方法引用:Class::new
public void constructorRef() {
// Lambda形式
Supplier<List<String>> lambda = () -> new ArrayList<>();
// 方法引用形式
Supplier<List<String>> ref = ArrayList::new;
// 带参数的构造器
Function<String, Integer> func = Integer::new; // new Integer(String)
List<String> list = ref.get();
}
}
十一、函数式编程
11.1 常用函数式接口
import java.util.function.*;
public class FunctionalInterfacesDemo {
// 1. Predicate<T>:断言(返回boolean)
public void predicateDemo() {
Predicate<Integer> isEven = n -> n % 2 == 0;
Predicate<String> isNotEmpty = s -> s != null && !s.isEmpty();
Predicate<Integer> isPositive = n -> n > 0;
System.out.println(isEven.test(4)); // true
System.out.println(isPositive.test(-1)); // false
// 组合Predicate
Predicate<Integer> isEvenAndPositive = isEven.and(isPositive);
Predicate<Integer> isEvenOrPositive = isEven.or(isPositive);
Predicate<Integer> isNotEven = isEven.negate();
}
// 2. Function<T,R>:转换(输入T,输出R)
public void functionDemo() {
Function<String, Integer> length = String::length;
Function<Integer, String> toString = Object::toString;
Function<String, String> toUpper = String::toUpperCase;
// 组合Function
Function<String, String> upperThenLength =
toUpper.andThen(length).andThen(toString);
// 使用
Integer len = length.apply("Hello"); // 5
String result = upperThenLength.apply("Hello"); // "5"
}
// 3. Consumer<T>:消费(无返回值)
public void consumerDemo() {
Consumer<String> printer = System.out::println;
Consumer<List<String>> listPrinter = list -> list.forEach(System.out::println);
// 组合Consumer
Consumer<String> logAndPrint =
s -> System.out.println("Log: " + s).andThen(printer);
printer.accept("Hello");
}
// 4. Supplier<T>:供应(无输入,返回T)
public void supplierDemo() {
Supplier<Double> random = Math::random;
Supplier<LocalDateTime> now = LocalDateTime::now;
Supplier<List<String>> emptyList = ArrayList::new;
Double value = random.get();
LocalDateTime current = now.get();
}
// 5. UnaryOperator<T>:一元操作(Function的特例)
public void unaryOperatorDemo() {
UnaryOperator<String> toUpper = String::toUpperCase;
UnaryOperator<Integer> square = n -> n * n;
String result = toUpper.apply("hello"); // "HELLO"
Integer squared = square.apply(5); // 25
}
// 6. BinaryOperator<T>:二元操作(BiFunction的特例)
public void binaryOperatorDemo() {
BinaryOperator<Integer> add = Integer::sum;
BinaryOperator<Integer> max = Integer::max;
Integer sum = add.apply(10, 20); // 30
Integer maximum = max.apply(10, 20); // 20
}
// 7. BiFunction<T,U,R>:双参数函数
public void biFunctionDemo() {
BiFunction<String, Integer, String> repeat = (s, n) -> s.repeat(n);
BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
String repeated = repeat.apply("Hi", 3); // "HiHiHi"
}
}
11.2 Stream API
public class StreamDemo {
public void streamOperations() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 中间操作
List<Integer> result = numbers.stream()
.filter(n -> n % 2 == 0) // 过滤偶数
.map(n -> n * 2) // 乘以2
.distinct() // 去重
.sorted(Comparator.reverseOrder()) // 降序排序
.limit(3) // 限制3个
.skip(1) // 跳过1个
.peek(n -> System.out.println("处理: " + n)) // 调试
.collect(Collectors.toList()); // 终端操作:收集
// 常用终端操作
// count()
long count = numbers.stream().filter(n -> n > 5).count();
// forEach()
numbers.stream().forEach(System.out::println);
// reduce()
Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
Optional<Integer> max = numbers.stream().reduce(Integer::max);
// anyMatch / allMatch / noneMatch
boolean hasEven = numbers.stream().anyMatch(n -> n % 2 == 0);
boolean allPositive = numbers.stream().allMatch(n -> n > 0);
// findFirst / findAny
Optional<Integer> first = numbers.stream().findFirst();
Optional<Integer> any = numbers.parallelStream().findAny();
// toArray
Integer[] array = numbers.stream().toArray(Integer[]::new);
}
// 分组和聚合
public void groupingDemo() {
List<Person> persons = Arrays.asList(
new Person("张三", "北京", 25),
new Person("李四", "上海", 30),
new Person("王五", "北京", 28),
new Person("赵六", "上海", 32)
);
// 按城市分组
Map<String, List<Person>> byCity = persons.stream()
.collect(Collectors.groupingBy(Person::getCity));
// 按城市分组,统计人数
Map<String, Long> countByCity = persons.stream()
.collect(Collectors.groupingBy(Person::getCity, Collectors.counting()));
// 按城市分组,计算平均年龄
Map<String, Double> avgAgeByCity = persons.stream()
.collect(Collectors.groupingBy(Person::getCity,
Collectors.averagingInt(Person::getAge)));
// 多级分组
Map<String, Map<Integer, List<Person>>> multiGroup = persons.stream()
.collect(Collectors.groupingBy(Person::getCity,
Collectors.groupingBy(Person::getAge)));
}
}
十二、异常处理中的方法
public class ExceptionMethodDemo {
// 1. 方法声明抛出异常
public void readFile(String path) throws IOException {
if (path == null) {
throw new IllegalArgumentException("路径不能为null");
}
Files.readAllLines(Paths.get(path));
}
// 2. 方法内部捕获异常
public void safeReadFile(String path) {
try {
Files.readAllLines(Paths.get(path));
} catch (IOException e) {
System.err.println("读取文件失败: " + e.getMessage());
// 记录日志、返回默认值等
}
}
// 3. 异常转译(包装异常)
public void wrappedException(String path) throws ServiceException {
try {
Files.readAllLines(Paths.get(path));
} catch (IOException e) {
throw new ServiceException("文件服务错误", e);
}
}
// 4. 自定义异常
class ServiceException extends Exception {
public ServiceException(String message) {
super(message);
}
public ServiceException(String message, Throwable cause) {
super(message, cause);
}
}
// 5. try-with-resources自动关闭
public void tryWithResources() {
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}
}
十三、方法内联与性能
public class MethodPerformanceDemo {
// 1. 小方法适合内联
private int add(int a, int b) {
return a + b; // 简单操作,JVM会内联
}
// 2. 频繁调用的方法应简洁
public void hotMethod() {
for (int i = 0; i < 1000000; i++) {
// 调用简洁的方法
int result = add(i, i + 1);
}
}
// 3. 避免不必要的getter/setter(JVM可优化)
private String name;
public String getName() {
return name; // JVM会内联此类简单访问
}
// 4. 性能测试
public void performanceTest() {
long start = System.nanoTime();
// 执行测试
long duration = System.nanoTime() - start;
System.out.println("执行时间: " + duration + " ns");
}
}
十四、最佳实践
14.1 方法设计原则
public class MethodBestPractices {
// 1. 单一职责:一个方法只做一件事
// 不好
public void processUser(String name, int age, String email) {
// 验证、保存、发送邮件混在一起
}
// 好
public boolean validateUser(String name, int age, String email) { }
public void saveUser(String name, int age, String email) { }
public void sendWelcomeEmail(String email) { }
// 2. 方法命名规范
// 动词开头,驼峰命名
public void calculateTotal() { }
public boolean isValidEmail(String email) { }
public User findUserById(Long id) { }
// 3. 参数数量控制
// 避免超过3-4个参数
// 不好
public void createUser(String name, int age, String email, String phone,
String address, String city, String country) { }
// 好:使用对象封装
public void createUser(UserDto userDto) { }
// 4. 返回类型规范
// 返回空集合而非null
public List<String> getNames() {
return Collections.emptyList(); // 而不是返回null
}
// 返回Optional
public Optional<User> findUser(Long id) {
return Optional.ofNullable(userMap.get(id));
}
// 5. 方法可见性
private void internalHelper() { } // 内部使用
protected void forSubclass() { } // 供子类扩展
public void apiMethod() { } // 公开API
}
14.2 常见反模式
public class MethodAntiPatterns {
// 反模式1:过长的方法
public void tooLongMethod() {
// 数百行代码
// 应该拆分为多个小方法
}
// 反模式2:过多的参数
public void tooManyParams(int p1, int p2, int p3, int p4, int p5,
int p6, int p7, int p8, int p9, int p10) {
// 使用对象封装参数
}
// 反模式3:过多的返回值
public int[] badMethod() {
// 返回多个值但含义不明确
return new int[]{1, 2, 3}; // 各值含义不清
}
// 反模式4:副作用
private List<String> list = new ArrayList<>();
public void methodWithSideEffect(String item) {
// 修改全局状态,应该避免或明确文档说明
list.add(item);
}
// 反模式5:使用异常控制流程
public void useExceptionForFlow() {
try {
// 正常流程
} catch (Exception e) {
// 控制流程
}
}
}
Java函数(方法)是Java程序的基本构建块。从基础的方法声明、参数传递、方法重载,到高级的Lambda表达式、函数式接口、Stream API,Java的函数体系已经发展成为一套完整而强大的编程范式。
来源:
https://dnuhf.cn/category/food.html