一、方法引用:
把已经有的方法拿过来用,当做函数式接口中抽象方法的方法体
1.方法引用条件:
①.引用处必须是函数式接口
②.被引用的方法必须已经存在
③.被引用方法的形参和返回值,需要跟抽象方法保持一致
④.被引用方法的功能要满足当前需求
代码演示:
package a10functiondemo;
import java.util.Arrays;
import java.util.Comparator;
public class FunctionDemo1 {
public static void main(String[] args) {
//创建一个数组进行倒序排列
Integer[] arr = {3, 5, 4, 1, 6, 2};
//匿名内部类
/* Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
*/
//Lambda表达式
//Arrays.sort(arr, (o1, o2) -> o2 - o1);
//方法引用
//表示引用FunctionDemo1类里面的subtraction方法
//把这个方法当做抽象方法的方法体
Arrays.sort(arr, FunctionDemo1::subtraction);
System.out.println(Arrays.toString(arr));
}
public static int subtraction(int num1,int num2){
return num2-num1;
}
}
运行结果:
二、方法引用的分类:
1.引用静态方法
格式:类名::静态方法
范例:Integet::parseInt
练习:集合中有以下数字,要求把他们变成int类型“1” “2” “3” “4” “5”
package a10functiondemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Function;
public class FunctionDemo2 {
public static void main(String[] args) {
//1.创建集合并添加元素
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"1","2","3","4","5");
//2.常规方法:
/* ArrayList<Integer> list2=new ArrayList<>();
for (String s : list) {
int i=Integer.parseInt(s);
list2.add(i);
}
*/
//方法引用:
/* list.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
int i = Integer.parseInt(s);
return i;
}
}).forEach(s-> System.out.println(s));
*/
list.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));
}
}
运行结果:
2.引用成员方法
格式:对象::成员方法
(1)引用其他类的成员方法:其他类对象::方法名
(2)引用本类的成员方法:this::方法名(引用处不能是静态方法)
(3)引用父类的成员方法:super::方法名(引用处不能是静态方法)
练习1:集合中有一些名字,按照要求过滤数据
其他类中的方法:
package a10functiondemo;
public class StringOperation {
public boolean stringJudge(String s){
return s.startsWith("林")&&s.length()==3;
}
}
测试类:
package a10functiondemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
public class FunctionDemo3 {
public static void main(String[] args) {
//1.创建集合
ArrayList<String> list=new ArrayList<>();
//2.添加数据
Collections.addAll(list,"林静恒","庄凡心","盛望","林水程","林辰");
//过滤数据(只要以林开头的,而且名字是三个字)
//list.stream().filter(s->s.startsWith("林")).filter(s->s.length()==3).forEach(s-> System.out.println(s));
/* list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("林")&&s.length()==3;
}
}).forEach(s-> System.out.println(s));
*/
list.stream().filter(new StringOperation()::stringJudge).forEach(s -> System.out.println(s));
System.out.println("------------");
//如果方法在本类中
//用this会报错,因为静态中没有this,若想用只能new本类名
list.stream().filter(new FunctionDemo3()::stringJudge).forEach(s -> System.out.println(s));
}
public boolean stringJudge(String s){
return s.startsWith("林")&&s.length()==3;
}
}
运行结果:
3.引用构造方法
格式:类名::new
范例:Student::new
练习:集合里面存储姓名和年龄,比如:鹿晗,34
要求:将数据封装成Student对象并收集到List集合中
学生类:
package a10functiondemo;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String str) {
String[] arr = str.split(",");
this.name = arr[0];
this.age = Integer.parseInt(arr[1]);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
测试类:
package a10functiondemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class FunctionDemo4 {
public static void main(String[] args) {
//创建集合对象
ArrayList<String> list=new ArrayList<>();
//2.添加数据
Collections.addAll(list,"鹿晗,34" ,"天空,42","王瑞昌,27","林更新,37","魏大勋,35","刘学义,34","肖宇梁,29");
//把数据封装成Student对象并收集到List集合中
/* List<Student> newList = list.stream().map(new Function<String, Student>() {
@Override
public Student apply(String s) {
String[] arr = s.split(",");
String name = arr[0];
int age = Integer.parseInt(arr[1]);
return new Student(name, age);
}
}).collect(Collectors.toList());
System.out.println(newList);
*/
List<Student> newList2 = list.stream().map(Student::new).collect(Collectors.toList());
System.out.println(newList2);
}
}
运行结果:
4.其他调用方式
(1)使用类名引用成员方法
格式:类名::成员方法
范例:String::substring
方法引用的规则:
①需要有函数式接口
②被引用的方法必须已经存在
③被引用方法的形参,需要跟抽象方法的第二个形参到最后的形参保持一致,返回值需要保持一致
④被引用方法的功能需要满足当前的需求
抽象方法形参的详解:
①第一个参数:
表示被引用方法的调用者,决定了可以引用哪些类中的方法
在Stream流当中,第一个参数一般都表示流里面的每一个数据
假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法
②第二个参数到最后一个参数:
跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法
练习:集合里面一些字符串,变成大写后输出
局限性:
不能引用所有类中的成员方法,是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法
package a10functiondemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class FunctionDemo5 {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"aaa","bbb","ccc","ddd");
/* list.stream().map(new Function<String, String>() {
@Override
public String apply(String s) {
return s.toUpperCase();
}
}).forEach(s-> System.out.println(s));
*/
list.stream().map(String::toUpperCase).forEach(s-> System.out.println(s));
}
}
运行结果:
(2)引用数组的构造方法
格式:数据类型[]::new
范例:int[] ::new
注意:数组的类型需要跟流中的数据保持一致
练习:集合中存储一些整数,收集到集合当中
package a10functiondemo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;
public class FunctionDemo6 {
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<>();
Collections.addAll(list,1,2,3,4,5);
/* Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {
@Override
public Integer[] apply(int value) {
return new Integer[value];
}
});
System.out.println(Arrays.toString(arr));
*/
Integer[] arr2 = list.stream().toArray(Integer[]::new);
System.out.println(Arrays.toString(arr2));
}
}
运行结果: