1、介绍
-
方法引用:把已经存在的方法拿过来用,当做函数式接口中的抽象方法的方法体。
-
方法引用符:
::
-
方法应用时的注意事项:
- 需要有函数式接口
- 被引用方法最好已经存在,这样才够简洁,不然自己又要定义一个方法。
- 被引用方法的形参和返回值需要和抽象方法保持一致
- 被引用方法的功能要满足当前的需求
-
方法引用分类:
- 引用静态方法
- 引用成员方法
- 引用其他类的成员方法
- 引用本类的成员方法
- 引用父类的成员方法
- 引用构造方法
- 其他调用方式
- 使用类名引用成员方法
- 引用数组的构造方法
2、使用类名引用静态方法
格式:类名:静态方法
范例:Integer::parseInt
// 创建集合并添加元素
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "111", "222", "333", "444");
// 需求:将集合中的字符串转换成整型
// 输出:111 222 333 444
list.stream().map(Integer::parseInt).forEach(s -> System.out.print(s + " "));
3、使用对象引用成员方法
格式:对象:成员方法
- 其他类:
其他类对象::方法名
- 本类:
this::方法名
- 父类:
super::方法名
注意:静态方法中没有this和super关键字
-
创建StringOperation类
public class StringOperation { public boolean stringJudge(String s) { return s.startsWith("张") && s.length() == 3; } }
-
引用其他类成员方法
// 引用成员方法 public class FunctionQuote02 { public static void main(String[] args) { // 1.创建集合 ArrayList<String> list = new ArrayList<>(); // 2. 添加数据 Collections.addAll(list, "张无忌", "周芷若", "张三丰", "张强", "赵敏"); // 3.过滤数据:只要张开头,而且名字是三个字的 list.stream().filter(new StringOperation()::stringJudge).forEach(s -> System.out.println(s)); } }
4、使用类名引用构造方法
格式:类名::new
范例:Student::new
-
编写Student类
public class Student { String name; int age; // 重写构造方法供FunctionQuote03调用 public Student(String str) { String[] splits = str.split(","); this.name = splits[0]; this.age = Integer.parseInt(splits[1]); } .... }
-
需求实现
// 引用构造方法 public class FunctionQuote03 { public static void main(String[] args) { // 1.创建集合对象 ArrayList<String> list = new ArrayList<>(); // 2.添加数据 Collections.addAll(list,"张无忌,14","张强,16","赵敏,21","周芷若,24","张三丰,56"); // 3.将list中的数据封装到Student中,并收集到List集合中 list.stream().map(Student::new).forEach(s-> System.out.println(s)); } }
5、使用类名引用成员方法
格式:类名::成员方法
范例:String::substring
方法引用规则:
- 被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。
- 其他规则与上方介绍中一致
抽象方法参数详解:
- 第一个参数:表示被引用方法的调用者,决定了可以引用那些类中的方法,在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法。
- 第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要的是无参的成员方法。
局限性:
- 不能引用所有类中的成员方法,跟抽象方法的第一个参数有关,这个参数是什么类型,那么就只能引用这个类中的方法。
// 使用类名引用成员方法
public class FunctionQuote04 {
public static void main(String[] args) {
// 1.创建集合
ArrayList<String> list = new ArrayList<>();
// 2.添加数据
Collections.addAll(list, "aaa", "bbb", "ccc");
// 将数据变大写后输出
// 输出:AAA BBB CCC
list.stream().map(String::toUpperCase).forEach(s-> System.out.print(s + " "));
}
}
6、引用数组的构造方法
格式:数据类型[]::new
范例:int[]::new
// 引用数组的构造方法
public class FunctionQuote05 {
public static void main(String[] args) {
// 1.创建集合并添加元素
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5, 6);
// 2.收集到数组中
Integer[] array = list.stream().toArray(Integer[]::new);
// 输出:[1, 2, 3, 4, 5, 6]
System.out.println(Arrays.toString(array));
}
}
7、综合案例
7.1、案例一
// 综合案例一
public class FunctionQuote06 {
public static void main(String[] args) {
// 1. 创建集合并添加元素
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌,14", "张强,16", "赵敏,21", "周芷若,24", "张三丰,56");
// 2.先把字符串变成Student对象,然后把Student对象收集起来
Student[] array = list.stream().map(Student::new).toArray(Student[]::new);
System.out.println(Arrays.toString(array));
}
}
7.2、案例二
// 综合案例二
public class FunctionQuote07 {
public static void main(String[] args) {
// 1.创建集合
ArrayList<Student> list = new ArrayList<>();
Collections.addAll(list,
new Student("zhangsan",23),
new Student("lisi",24),
new Student("wangwu",25));
// 3.获取姓名并放到数组中
String[] array = list.stream().map(Student::getName).toArray(String[]::new);
// 输出:[zhangsan, lisi, wangwu]
System.out.println(Arrays.toString(array));
}
}