方法引用案例

wen java案例 2

本文目录导读:

方法引用案例

  1. Java 方法引用案例详解
  2. 方法引用的四种类型
  3. 实战案例
  4. 方法引用 vs Lambda 对照表
  5. 使用建议

Java 方法引用案例详解

方法引用是 Lambda 表达式的简化写法,用 符号表示,下面通过实际案例来展示各种类型的方法引用。

方法引用的四种类型

类型 语法 对应 Lambda
静态方法引用 ClassName::staticMethod (args) -> ClassName.staticMethod(args)
实例方法引用(特定对象) instance::instanceMethod (args) -> instance.instanceMethod(args)
实例方法引用(类类型) ClassName::instanceMethod (obj, args) -> obj.instanceMethod(args)
构造器引用 ClassName::new (args) -> new ClassName(args)

实战案例

案例1:静态方法引用

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
public class StaticMethodRef {
    public static void main(String[] args) {
        // 场景1:对列表进行排序
        List<String> names = Arrays.asList("Tom", "Alice", "Bob", "Charlie");
        // Lambda 写法
        names.sort((s1, s2) -> String.compareToIgnoreCase(s1, s2));
        // 方法引用写法(静态方法引用)
        names.sort(String::compareToIgnoreCase);
        System.out.println("排序结果: " + names); // [Alice, Bob, Charlie, Tom]
        // 场景2:使用 Function 接口
        Function<Integer, String> intToString = String::valueOf;
        System.out.println(intToString.apply(123).length()); // 3
        // 场景3:使用 Predicate 判断空字符串
        Predicate<String> isEmpty = String::isEmpty;
        System.out.println(isEmpty.test("")); // true
        System.out.println(isEmpty.test("Hello")); // false
    }
}

案例2:实例方法引用(特定对象)

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
public class InstanceMethodRef {
    public static void main(String[] args) {
        // 创建一个 StringBuilder 对象
        StringBuilder sb = new StringBuilder("Hello ");
        // 场景1:Consumer 接口 - 对特定对象的方法引用
        Consumer<String> appendToSb = sb::append;
        appendToSb.accept("World!");
        System.out.println(sb.toString()); // Hello World!
        // 场景2:Function 接口
        List<String> names = List.of("Apple", "Banana", "Cherry");
        // Lambda 写法
        Function<String, Integer> lenLambda = (s) -> s.length();
        // 方法引用写法(更简洁,使用特定对象的方法)
        Function<String, Integer> lenRef = String::length; // 这是类类型实例方法引用
        System.out.println(names.stream()
                .map(String::length)  // 类类型实例方法引用
                .toList()); // [5, 6, 6]
        // 场景3:特定对象的方法引用
        List<String> toUpper = new ArrayList<>(List.of("hello", "world"));
        System.out.println(toUpper.stream()
                .map(String::toUpperCase)
                .toList()); // [HELLO, WORLD]
    }
}

案例3:实例方法引用(类类型 - 需要参数)

import java.util.Arrays;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Function;
public class ClassInstanceMethodRef {
    public static void main(String[] args) {
        // 场景1:比较两个字符串(忽略大小写)
        List<String> words = Arrays.asList("Apple", "banana", "Cherry", "apple");
        // 使用 BiPredicate 接口(接收两个参数)
        BiPredicate<String, String> equalsIgnoreCase = String::equalsIgnoreCase;
        System.out.println("Apple 与 apple 相等?: " + 
                equalsIgnoreCase.test("Apple", "apple")); // true
        // 场景2:查找列表中是否存在特定元素
        boolean hasApple = words.stream()
                .anyMatch("apple"::equalsIgnoreCase);  // 特定对象实例方法引用
        System.out.println("列表包含 apple: " + hasApple); // true
        // 场景3:复杂对象的方法引用
        List<Person> persons = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Charlie", 35)
        );
        // 将 Person 对象映射为姓名
        Function<Person, String> getName = Person::getName;
        System.out.println("人员姓名: " + persons.stream()
                .map(getName)
                .toList()); // [Alice, Bob, Charlie]
    }
}
class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() { return name; }
    public int getAge() { return age; }
}

案例4:构造器引用

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
public class ConstructorRef {
    public static void main(String[] args) {
        // 场景1:无参构造器引用
        Supplier<List<String>> listFactory = ArrayList::new;
        List<String> list = listFactory.get();
        list.add("Hello");
        System.out.println("创建的空列表: " + list); // [Hello]
        // 场景2:有参构造器引用
        Function<String, StringBuilder> sbFactory = StringBuilder::new;
        StringBuilder sb = sbFactory.apply("Hello World");
        System.out.println("构造器创建: " + sb.toString()); // Hello World
        // 场景3:数组构造器引用
        Function<Integer, String[]> stringArray = String[]::new;
        String[] arr = stringArray.apply(5);
        System.out.println("创建数组长度: " + arr.length); // 5
        // 场景4:结合 Stream 使用
        List<String> names = List.of("Alice", "Bob", "Charlie");
        List<Student> students = names.stream()
                .map(Student::new)  // 构造器引用
                .toList();
        students.forEach(System.out::println);
    }
}
class Student {
    private String name;
    public Student(String name) {
        this.name = name;
        System.out.println("为学生创建了: " + name);
    }
    @Override
    public String toString() {
        return "Student{" + "name='" + name + '\'' + '}';
    }
}

案例5:综合实战 - 员工数据处理

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ComprehensiveDemo {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
            new Employee("张伟", 28, 18000, "技术部"),
            new Employee("李娜", 35, 22000, "产品部"),
            new Employee("王强", 42, 30000, "管理部"),
            new Employee("赵敏", 24, 15000, "技术部"),
            new Employee("钱进", 38, 25000, "市场部")
        );
        System.out.println("=== 原始数据 ===");
        employees.forEach(System.out::println);
        // 场景1:排序(方法引用)
        System.out.println("\n=== 按年龄排序 ===");
        employees.stream()
                .sorted(Comparator.comparingInt(Employee::getAge))
                .forEach(System.out::println);
        // 场景2:工资过滤 + 统计
        System.out.println("\n=== 工资超过20000的员工 ===");
        double avgSalary = employees.stream()
                .filter(e -> e.getSalary() > 20000)
                .mapToInt(Employee::getSalary)
                .average()
                .orElse(0);
        System.out.println("平均工资: " + avgSalary);
        // 场景3:按部门分组
        System.out.println("\n=== 按部门分组 ===");
        Map<String, List<Employee>> byDept = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment));
        byDept.forEach((dept, empList) -> {
            System.out.println(dept + ": " + empList.size() + "人");
        });
        // 场景4:获取所有姓名
        System.out.println("\n=== 员工姓名 ===");
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
        // 场景5:自定义比较器
        System.out.println("\n=== 按工资降序 ===");
        employees.stream()
                .sorted(Comparator.comparingInt(Employee::getSalary).reversed())
                .map(Employee::getName)
                .forEach(e -> System.out.println("员工: " + e));
    }
}
class Employee {
    private String name;
    private int age;
    private int salary;
    private String department;
    public Employee(String name, int age, int salary, String department) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.department = department;
    }
    // Getters
    public String getName() { return name; }
    public int getAge() { return age; }
    public int getSalary() { return salary; }
    public String getDepartment() { return department; }
    @Override
    public String toString() {
        return String.format("%s(%d岁,工资%d,%s)", name, age, salary, department);
    }
}

方法引用 vs Lambda 对照表

// 1. 静态方法引用
Function<Integer, String> f1 = String::valueOf;        // 方法引用
Function<Integer, String> f2 = i -> String.valueOf(i); // Lambda
// 2. 实例方法引用(直接调用)
List<String> list = List.of("a", "b");
list.forEach(System.out::println);                    // 方法引用
list.forEach(s -> System.out.println(s));             // Lambda
// 3. 对象引用(比较)
Comparator<String> c1 = String::compareToIgnoreCase;  // 方法引用
Comparator<String> c2 = (a, b) -> a.compareToIgnoreCase(b); // Lambda
// 4. 构造器引用
Supplier<List<String>> s1 = ArrayList::new;           // 方法引用
Supplier<List<String>> s2 = () -> new ArrayList<>();  // Lambda

使用建议

适合使用方法引用

  • 已有现成的方法直接匹配函数式接口
  • 代码更加简洁、易读
  • 标准库中如 Stream 操作

不适合使用方法引用

  • 方法调用需要额外参数(非直接匹配)
  • Lambda 中代码量超过一行
  • 需要进行逻辑判断或计算
// 反例:方法引用反而更复杂
Function<String, String> f = s -> {
    String upper = s.toUpperCase();
    return upper + "-suffix";
}; // 这种情况必须用 Lambda

方法引用的核心价值在于简化代码,让代码更具可读性,选择标准:

  1. 方法恰好匹配接口参数 → 使用静态引用
  2. 需要对对象进行操作 → 使用实例引用
  3. 需要创建新对象 → 使用构造器引用
  4. 逻辑复杂或需要额外处理 → 继续使用 Lambda

掌握方法引用的关键是要理解函数式接口的参数传递规则,当方法签名与接口方法签名匹配时,就可以使用 简化代码。

抱歉,评论功能暂时关闭!