Java函数知识点大全(四)

简介: 教程来源 https://dnuhf.cn/ 本文系统讲解Java函数式编程核心:Lambda表达式(含语法、方法引用四种形式)、常用函数式接口(Predicate/Function/Consumer等)、Stream API(中间/终端操作、分组聚合)、异常处理技巧及方法设计最佳实践,涵盖从基础到高级的完整知识体系。

十、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

相关文章
|
3月前
|
Java
Java函数知识点大全(三)
教程来源 https://ljtgc.cn/ 本文系统讲解Java面向对象核心机制:构造方法(含无参、有参、私有、拷贝及构造器链)、方法重写规则与@Override注解、抽象类与接口方法(含默认/静态/私有方法)及函数式接口,辅以典型代码示例,助你深入掌握Java OOP精髓。
|
3月前
|
Java
Java函数知识点大全(二)
教程来源 https://www.xcfsr.cn/category/software-dev.html 本节详解Java核心编程技术:递归(含阶乘、斐波那契、汉诺塔等经典案例及尾递归、记忆化优化)、静态方法(工具类、工厂模式、单例实现)与实例方法(this用法、链式调用)。内容精炼实用,适合深入理解面向对象编程精髓。
|
Dubbo Java 应用服务中间件
微服务技术系列教程(30) - Dubbo-SpringCloud与Dubbo区别
微服务技术系列教程(30) - Dubbo-SpringCloud与Dubbo区别
661 0
|
3月前
|
存储 缓存 前端开发
MVVM框架知识点大全(三)
教程来源 https://ljtgc.cn/category/mobile-games.html 本文系统讲解MVVM架构的性能优化与最佳实践:涵盖数据绑定、集合更新、异步处理、懒加载、更新频率控制及轻量框架选型;强调三层分离、依赖注入、命令绑定、命名规范、单元测试与生命周期管理,并对比多端框架实现,助力高效开发。
|
3月前
|
搜索推荐 安全 数据可视化
新手如何利用PHP快速搭建个人博客(无代码基础也能上手)
个人博客是分享生活、记录学习、展示个人能力的重要载体,很多新手都想搭建属于自己的个人博客,但苦于没有代码基础,不知道从何入手。
671 0
|
3月前
|
前端开发 编译器
MVVM框架知识点大全(二)
教程来源 https://dnuhf.cn/category/health.html View是MVVM中用户交互的界面层,仅负责UI展示与事件传递,通过声明式数据绑定关联ViewModel,实现状态自动同步。它被动响应、不涉业务逻辑,与ViewModel保持单向依赖,确保可测试性与解耦。
|
3月前
|
XML 人工智能 JSON
markdown 为什么AI都用它
Markdown是AI时代的“通用语”:轻量省Token、结构清晰易读易解析、跨平台兼容强,且因训练数据丰富成为大模型默认输出格式。它平衡人类可读性与机器可解析性,让AI响应更规范、高效、低成本。(239字)
|
2月前
|
数据采集 缓存 安全
【HTTP】HTTP协议核心体系:请求方法与状态码全结构化解析(附《思维导图》)
本文系统解析HTTP/1.1请求方法与状态码:厘清安全/幂等本质,详解9种方法语义、约束与误区;全覆盖状态码全分类(1xx/2xx/3xx/4xx/5xx核心场景)的定义、场景及关键区分(如301/308、401/403、502/504);强调RESTful实践与高频红线,助力构建健壮、规范的Web服务。
|
2月前
|
存储 缓存 NoSQL
CAS 无锁并发深度解析:从 CPU 原语、JDK 源码到生产实战与避坑指南
本文深度解析Java中CAS(Compare-And-Swap)无锁并发机制:从CPU底层LOCK+CMPXCHG指令、JDK 17源码(Unsafe/VarHandle)、原子类实现,到ABA、自旋飙升、伪共享等五大生产陷阱及避坑方案,并附3个实战案例。助你真正吃透CAS核心逻辑与最佳实践。
235 3
|
2月前
|
数据采集 缓存 JSON
开源 OpenClaw A 股数据插件:指数 / ETF / 个股 / 期权统一接口,已上架 ClawHub
开源OpenClaw A股数据插件上线ClawHub!统一支持指数/ETF/个股/挂牌期权,提供稳定、可降级、易缓存的标准化数据接口,专为Agent/Workflow设计。MIT协议,安装即用:`openclaw plugins install @shaoxing-xie/openclaw-data-china-stock`。GitHub与ClawHub双链可查。免责声明:仅限技术研究,不构成投资建议。(239字)

热门文章

最新文章