【Java集合框架】3 - 17 方法引用
§3-17 方法引用
3-17.1 概述
方法引用(method reference)是 Java 8 所引入的新特性。方法引用是一种特殊的 Lambda 表达式,通过引用已存在的方法进一步简化 Lambda 表达式,让编译器处理参数的传递。
若 Lambda 表达式仅仅只是调用其他方法,则可以使用方法引用。
在正式介绍方法引用的使用方法和情况前,先要明确方法引用的使用条件:
- 方法引用处必须是函数式接口;
- 被引用的方法必须存在,所有的引用需要使用运算符
::
; - 被引用方法的型参与返回值需要与抽象方法所定义的形参和返回值一致;
- 被引用的方法应当满足当前需求;
接下来从四种不同的情况出发,讨论方法引用的使用。
3-17.2 引用静态方法
引用一个类中的静态方法,方法是:
ContainingClass::staticMethodName
需求:把集合中的元素变为整型,其中含有 "1", "2", "3", "4", "5"
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4", "5");
//流的映射方法:将一个类型映射到另一类型
//使用 Lambda
list.stream().map(s -> Integer.parseInt(s)).forEach(integer -> System.out.println(integer));
System.out.println("===========");
//静态方法引用,关注方法做什么,希望将字符串转到整型,Integer.parseInt即可
list.stream().map(Integer::parseInt).forEach(System.out::println);
3-17.3 引用具体对象的成员方法
引用成员方法,根据类之间的关系又可分为三种。
引用来自其它类的成员方法、来自本类(当前类)或父类的成员方法,方法是:
containingObject::instanceMethodName
this::instanceMethodName
super::instanceMethodName
注意:引用处(调用语句所在方法)不能是静态方法,因为本身并不存在 this
指针,因此无法直接使用 this
和 super
关键字。
需求:将集合中以 ”张“ 开头且长度为 3 的姓名过滤出来
ArrayList<String> names = new ArrayList<>();
Collections.addAll(names, "张无忌", "周芷若", "张三丰", "赵敏", "张强");
//使用 Lambda
names.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
System.out.println("==============");
//调用其他类的成员方法
names.stream().filter(new stringCheck()::check).forEach(System.out::println);
其中,check
来自于其他类 stringCheck
:
class stringCheck {
public boolean check(String s) {
if (s == null)
return false;
if (s.startsWith("张") && s.length() == 3)
return true;
return false;
}
}
3-17.4 引用某一类型任意对象的成员方法
引用某一类型任意对象的成员方法,方法为:
ContainingType::methodName
需求一:将集合中的姓名以忽略大小写的形式排列
ArrayList<String> names = new ArrayList<>();
Collections.addAll(names, "Zhangsan", "lisi", "WANGWU", "ZhaoLiu");
//使用 Lambda
names.stream().sorted(((o1, o2) -> o1.compareToIgnoreCase(o2))).forEach(System.out::println);
System.out.println("==============");
//使用方法引用
names.stream().sorted(String::compareToIgnoreCase).forEach(System.out::println);
System.out.println("==============");
需求二:将集合中的字符串变为全大写后输出
//需求:将集合中的字符串变为全大写后输出
ArrayList<String> strings = new ArrayList<>();
Collections.addAll(strings, "aaa", "bbb", "ccc", "ddd");
//使用 Lambda
strings.stream().map(s -> s.toUpperCase()).forEach(System.out::println);
System.out.println("==============");
//使用方法引用
names.stream().map(String::toUpperCase).forEach(System.out::println);
System.out.println("==============");
3-17.5 引用构造器
引用某一个类的构造器,方法为:
ClassName::new
也可以利用这种方法创建数组,方法为:
ClassName[]::new
需求一:将集合中所存储的姓名和年龄封装成 Student
对象。
先定义一个 Student
类,并重载构造器,使得 map
的形参接口能够直接仅调用该方法
public class Student {
private String name;
private int age;
public Student(String str) {
String[] arr = str.split(",");
this.name = arr[0];
this.age = Integer.parseInt(arr[1]);
}
//无参、空参构造、哈希值、equals、Getters & Setters
}
在测试类中
ArrayList<String> students = new ArrayList<>();
Collections.addAll(students, "张无忌,15", "周芷若,14", "赵敏,13", "张强,20", "张三丰,100"
, "张翠山,40", "张良,35", "王二麻子,37", "谢广坤,41");
//Lambda 表达式
students.stream()
.map(s -> new Student(s.split(",")[0], Integer.parseInt(s.split(",")[1]))).forEach(System.out::println);
System.out.println("==============");
//首先重载构造器,映射时直接方法引用
students.stream().map(Student::new).forEach(System.out::println);
System.out.println("==============");
需求二:将集合中存储的整数存储到数组中
//需求:将集合中存储的整数存储到数组中
ArrayList<Integer> integers = new ArrayList<>();
Collections.addAll(integers, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//Lambda 表达式
System.out.println(Arrays.toString(integers.toArray(value -> new Integer[value]))); //Integers[]
System.out.println("==============");
//构造方法引用
System.out.println(Arrays.toString(integers.toArray(Integer[]::new)));
System.out.println("==============");