方法引用是什么
把已经存在的方法拿过来用,当做函数式接口中抽象方法的方法体
方法引用符
::
方法引用的条件
1.需要有函数式接口
2.被引用方法必须已经存在
3.被引用方法的形参和返回值需要跟抽象方法保持一致
4.被引用方法的功能要满足当前的需求
方法引用的分类
引用静态方法
格式:类名 : : 静态方法
范例: Integer : : parseInt
代码演示
集合中有以下数字,要求把他们都变成int类型
“1”,“2”,“3”,“4”,”5“
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class Test1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4", "5");
//匿名内部类形式
list.stream()
.map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
})
.forEach(s -> System.out.println(s));
//lambda表达式
list.stream()
.map(s -> Integer.parseInt(s))
.forEach(s -> System.out.println(s));
//方法引用类型
//map中是函数式接口
//Integer类中的parseInt静态方法符合
//形参和返回值与抽象方法一致
//功能满足当前的需求
//因此可以进行方法引用
list.stream()
.map(Integer::parseInt)
.forEach(s -> System.out.println(s));
//1
//2
//3
//4
//5
}
}
引用成员方法
基本格式:对象 : : 成员方法
引用本类或父类的成员方法
本类:this : : 方法名
父类:super : : 方法名
注:因为this和super处的方法不是静态的,因此引用处也不能是静态
代码演示
设置一个界面,上面有两个按钮,对按钮利用方法引用的形式添加动作监听,要求涉及本类中的方法和父类中的方法
App类
public class App {
public static void main(String[] args) {
new LoginJFrame();
}
}
LoginJFrame类继承MyJFrame
import javax.swing.*;
import java.awt.event.ActionEvent;
public class LoginJFrame extends MyJFrame {
JButton go1;
JButton go2;
public LoginJFrame() {
//初始化界面
initFrame();
//定义按钮组件
go1 = new JButton("go(本类)");
go1.setBounds(180, 80, 150, 50);
this.getContentPane().add(go1);
go2 = new JButton("go(父类)");
go2.setBounds(30, 80, 150, 50);
this.getContentPane().add(go2);
//除了实现接口外
//还可以利用方法引用给按钮设置动作监听
go1.addActionListener(this::method1);//本类中的go被点击了
go2.addActionListener(super::method2);//父类中的go被点击了
}
public void method1(ActionEvent e) {
System.out.println("本类中的go被点击了");
}
//定义方法初始化界面
private void initFrame() {
//设置大小
this.setSize(400, 300);
//设置置顶
this.setAlwaysOnTop(true);
//设置居中
this.setLocationRelativeTo(null);
//设置关闭模式
this.setDefaultCloseOperation(3);
//设置解除默认居中放置,使用坐标决定组件位置
this.setLayout(null);
//设置界面可视
this.setVisible(true);
}
}
MyJFrame类继承JFrame
import javax.swing.*;
import java.awt.event.ActionEvent;
public class MyJFrame extends JFrame {
public void method2(ActionEvent e) {
System.out.println("父类中的go被点击了");
}
}
引用其他类的成员方法
格式:其他类对象 : : 方法名
代码演示
集合中有一些名字,按照要求过滤数据
数据:"张无忌","周芷若","赵敏","张强","张三丰"
要求:只要以张开头,而且名字是3个字的
测试类
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
//匿名内部类
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("张") && s.length() == 3;
}
}).forEach(s -> System.out.println(s));
//lambda表达式
list.stream()
.filter(s -> s.startsWith("张") && s.length() == 3)
.forEach(s -> System.out.println(s));
//方法引用
//需要先在别的类(StringOperation)中定义一个方法(stringJudge)
//使得该方法
//形参和返回值需跟抽象方法一致
//功能满足当前的需求
list.stream()
.filter(StringOperation::stringJudge)
.forEach(s -> System.out.println(s));
//张无忌
//张三丰
}
}
StringOperation 类
public class StringOperation {
public static boolean stringJudge(String s){
return s.startsWith("张")&&s.length()==3;
}
}
引用构造方法
格式:类名 : : new
范例:student : : new
代码演示
集合里面存储姓名和年龄,比如:张三,23
要求:将数据封装成Student对象并收集到List集合中
测试类
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三,23", "李四,24", "王五,25");
//匿名内部类
List<Student> newList1 = list.stream()
.map(new Function<String, Student>() {
@Override
public Student apply(String s) {
return new Student(s.split(",")[0],
Integer.parseInt(s.split(",")[1]));
}
}).collect(Collectors.toList());
//lambda表达式
List<Student> newList2 = list.stream()
.map(s -> new Student(s.split(",")[0],
Integer.parseInt(s.split(",")[1])))
.collect(Collectors.toList());
//方法引用
List<Student> newList3 = list.stream()
.map(Student::new)
.collect(Collectors.toList());
System.out.println(newList3);
//[Student{name='张三', age=23}, Student{name='李四', age=24}, Student{name='王五', age=25}]
}
}
Student类
public class Student {
private String name;
private int age;
public Student() {
}
//定义一个构造方法
//形参和返回值跟抽象方法一致
//功能要满足当前的需求
public Student(String s){
this.name = s.split(",")[0];
this.age = Integer.parseInt(s.split(",")[1]);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
其他引用方式
使用类名引用成员方法
格式:类名 : : 成员方法
范例:String : : substring
此方法引用有不同的规则:
1.需要有函数式接口
2.被引用的方法必须已经存在
3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。
4.被引用方法的功能需要满足当前的需求
抽象方法形参的详解:
第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法
在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法
第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法
弊端:
不能引用所有类中的成员方法,若抽象方法的第一个参数是A类型的,只能引用A类中的方法
代码演示
集合里面一些字符串,要求变成大写后进行输出
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class Test1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "aaa", "bbb", "ccc");
//匿名内部类
list.stream()
.map(new Function<String, String>() {
@Override
public String apply(String s) {
return s.toUpperCase();
}
})
.forEach(s -> System.out.println(s));
//lambda表达式
list.stream()
.map(s -> s.toUpperCase())
.forEach(s -> System.out.println(s));
//方法引用
list.stream()
.map(String::toUpperCase)
.forEach(s -> System.out.println(s));
//AAA
//BBB
//CCC
}
}
引用数组的构造方法
格式:数据类型[ ] : : new
范例:int[ ] : : new
代码演示
集合中存储一些整数,收集到数组当中
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;
public class Test2 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5);
//匿名内部类
Integer[] arr1 = list.stream()
.toArray(new IntFunction<Integer[]>() {
@Override
public Integer[] apply(int value) {
return new Integer[value];
}
});
//lambda表达式
Integer[] arr2 = list.stream()
.toArray(value -> new Integer[value]);
//方法引用
Integer[] arr3 = list.stream()
.toArray(Integer[]::new);
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
System.out.println(Arrays.toString(arr3));
//[1, 2, 3, 4, 5]
}
}