JAVA8中方法引用的用法

Java8中方法引用的用法


Stream流和Lambda表达式不懂的可以看我之前的文章:

Stream流的使用

lambda表达式用法超详细介绍

觉得方法引用有点难记,所以又重新专门梳理一遍它的用法。

1、静态方法的引用

静态方法引用用于直接调用类的静态方法。语法是 ClassName::staticMethod。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StringToIntExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("1", "2", "3");
        
        // 使用 Integer::parseInt 将字符串转换为整型
        List<Integer> integers = names.stream()
                                     .map(Integer::parseInt)
                                     .collect(Collectors.toList());
        
        System.out.println(integers); // 输出: [1, 2, 3]
    }
}

这里解释一下,如果不用方法引用如果用lambda表达式应该怎么写

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LambdaExpressionExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("1", "2", "3");
        
        // 使用 lambda 表达式创建新的 ArrayList
        List<Integer> integers = names.stream()
                              .map(s -> Integer.parseInt(s))
                              .collect(Collectors.toList());
        
        System.out.println(upperCaseNames); // 输出: [1, 2, 3]
    }
}

这里之所以可以这么写是因为lambda表达式可以用于简写函数式接口,而这里的s -> Integer.parseInt(s)就是一个函数式接口的简写,如下,Function接口的apply方法就是接收一个泛型参数,返回一个泛型类型的值。

所以也可以用lambda表达式实现,之所以说可以换成Integer::parseInt是因为刚好在Integer类里面有一个可以实现相同功能的静态方法,可以用来做替代。

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

甚至还可以换成最原始的匿名内部类的写法,因为lambda表达式是可以替代匿名内部类的。这样就可以完整的看出它的不同的简写的来由了。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.function.Function;

public class AnonymousInnerClassExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("1", "2", "3");
        
        // 使用匿名内部类创建新的 ArrayList
        List<Integer> integers = names.stream()
                                     .map(new Function<String, Integer>() {
                                         @Override
                                         public Integer apply(String s) {
                                             return Integer.parseInt(s);
                                         }
                                     })
                                     .collect(Collectors.toList());
        
        System.out.println(integers); // 输出: [1, 2, 3]
    }
}

2、实例方法引用

实例方法引用用于调用对象的实例方法。语法是 object::instanceMethod。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class InstanceMethodReferenceExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        String prefix = "User: ";

        // 使用实例方法引用添加前缀
        List<String> prefixedNames = names.stream()
                                          .map(prefix::concat)
                                          .collect(Collectors.toList());

        System.out.println(prefixedNames); // 输出: [User: Alice, User: Bob, User: Charlie]
    }
}

比如在转化成lambda表达式的写法

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LambdaExpressionExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        String prefix = "User: ";

        // 使用 lambda 表达式添加前缀
        List<String> prefixedNames = names.stream()
                                          .map(s -> prefix.concat(s))
                                          .collect(Collectors.toList());

        System.out.println(prefixedNames); // 输出: [User: Alice, User: Bob, User: Charlie]
    }
}

匿名内部类写法

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.function.Function;

public class AnonymousInnerClassExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        String prefix = "User: ";

        // 使用匿名内部类添加前缀
        List<String> prefixedNames = names.stream()
                                          .map(new Function<String, String>() {
                                              @Override
                                              public String apply(String s) {
                                                  return prefix.concat(s);
                                              }
                                          })
                                          .collect(Collectors.toList());

        System.out.println(prefixedNames); // 输出: [User: Alice, User: Bob, User: Charlie]
    }
}

相信你看了上面了几个例子之后一定也非常明了了。

3、类的实例方法引用

语法是 ClassName::instanceMethod。用于调用类里的实例方法。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SpecificInstanceMethodReferenceExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用特定对象的实例方法引用比较字符串长度
        names.sort(String::compareToIgnoreCase);

        System.out.println(names); // 输出: [Alice, Bob, Charlie]
    }
}

String::compareToIgnoreCase:这是类的实例方法引用。compareToIgnoreCase 是 String 类的一个实例方法,用于忽略大小写比较两个字符串。

  • 使用 Comparator 实现
import java.util.Arrays;
import java.util.List;
import java.util.Comparator;

public class SpecificInstanceMethodReferenceExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用特定对象的实例方法引用比较字符串长度
        names.sort(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareToIgnoreCase(s2);
            }
        });

        System.out.println(names); // 输出: [Alice, Bob, Charlie]
    }
}

哪些类可以使用类的实例方法引用?

类的实例方法引用可以用于任何具有实例方法的类。实例方法是指那些需要通过类的实例(对象)来调用的方法。以下是一些常见的类及其实例方法引用的例子:

  1. String

    • compareToIgnoreCase:忽略大小写比较两个字符串。
    • toLowerCase:将字符串转换为小写。
    • toUpperCase:将字符串转换为大写。
    • trim:去除字符串两端的空白字符。
    import java.util.Arrays;
    import java.util.List;
    
    public class StringMethodReferenceExample {
        public static void main(String[] args) {
            List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    
            // 使用类的实例方法引用比较字符串
            names.sort(String::compareToIgnoreCase);
    
            System.out.println(names); // 输出: [Alice, Bob, Charlie]
    
            // 使用类的实例方法引用转换为大写
            List<String> upperCaseNames = names.stream()
                                              .map(String::toUpperCase)
                                              .collect(Collectors.toList());
    
            System.out.println(upperCaseNames); // 输出: [ALICE, BOB, CHARLIE]
        }
    }
    
  2. Integer

    • intValue:将 Integer 对象转换为 int 值。
    • toString:将 Integer 对象转换为字符串。
  3. 自定义类

    • 您可以在自定义类中定义实例方法,并使用方法引用来引用这些方法。这个例子其实就很常见了,日常开发就会为了获取对象的一个属性(如果想获取多个属性的话可以考虑重写to)
    import java.util.Arrays;
    import java.util.List;
    
    class Person {
        private String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    
    public class CustomClassMethodReferenceExample {
        public static void main(String[] args) {
            List<Person> people = Arrays.asList(
                new Person("Alice"),
                new Person("Bob"),
                new Person("Charlie")
            );
    
            // 使用类的实例方法引用获取名字
            List<String> names = people.stream()
                                       .map(Person::getName)
                                       .collect(Collectors.toList());
    
            System.out.println(names); // 输出: [Alice, Bob, Charlie]
        }
    }
    

4、构造器引用

构造器引用用于直接调用类的构造方法。语法是 ClassName::new

让我们来看一个更实用的构造器引用的例子。假设我们有一个 Person 类,我们希望从一个包含名字的字符串列表中创建 Person 对象的列表。我们将使用构造器引用来实现这一点。

定义 Person

class Person {
    private String name;
    private int age;

    public Person(String name) {
        this.name = name;
        this.age = 0; // 默认年龄为 0
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

使用构造器引用创建 Person 对象的列表

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ConstructorReferenceExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 使用构造器引用创建新的 Person 对象列表
        List<Person> people = names.stream()
                                   .map(Person::new)
                                   .collect(Collectors.toList());

        // 输出结果
        for (Person person : people) {
            System.out.println(person); // 输出: Person{name='Alice', age=0}, Person{name='Bob', age=0}, Person{name='Charlie', age=0}
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

厌世小晨宇yu.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值