概念:通俗来讲,就是把已经有的方法拿过来用,当作函数式接口中抽象方法的方法体
使用规则:
1、引用处必须是函数式接口
2、被引用的方法必须已经存在
3、被引用的方法的形参和返回值需要跟抽象方法保持一致
4、被引用方法的功能要满足当前需求
符号:"::"
一、引用静态方法:
格式:类名 : : 静态方法
Integer::parseInt
例:
public class FunctionDemo1 {
public static void main(String[] args) {
/*
集合中有以下数字,要求把它们全变成int型
list={"1","2","3","4","5"};
*/
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(System.out::println);
//1
//2
//3
//4
//5
//使用方法引用的代码
list.stream().map(Integer::parseInt)
.forEach(System.out::println);
//1
//2
//3
//4
//5
}
}
二、引用成员方法:
格式:对象 : : 成员方法
1、其他类:其它类对象 : : 方法名
2、本类:this : : 方法名
3、父类:super : : 方法名
例 1:其他类的引用
public class FunctionDemo2 {
public static void main(String[] args) {
/*
集合中有一些名字,按照要求过滤数据
数据:"张三二","张五","赵六","李四","张麻子"
要求:以张字开头,且名字是三个字的
*/
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三二", "张五", "赵六", "李四", "张麻子");
//未使用方法引用
list.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length()==3)
.forEach(System.out::println);
//张三二
//张麻子
//使用方法引用
list.stream().filter(new StringOperation()::stringJudge)
.forEach(System.out::println);
//张三二
//张麻子
}
}
public class StringOperation {
public boolean stringJudge(String s){
return s.startsWith("张") && s.length()==3;
}
}
例 2:本类的引用
//未使用方法引用之前
public class LoginJFrame extends JFrame implements ActionListener {
public LoginJFrame(){
initJFrame();
initView();
this.setVisible(true);
}
JButton go=new JButton("Go");
private void initView() {
JLabel image=new JLabel();
image.setBounds(100,50,174,174);
image.setBackground(Color.red);
this.getContentPane().add(image);
go.setFont(new Font(null,1,20));
go.setBounds(120,274,150,50);
go.setBackground(Color.WHITE);
go.addActionListener(this);
this.getContentPane().add(go);
}
private void initJFrame() {
this.setTitle("...");
this.setSize(480,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setLayout(null);
this.getContentPane().setBackground(Color.white);
this.setAlwaysOnTop(true);
}
@Override
public void actionPerformed(ActionEvent e) {
Object obj=e.getSource();
if(obj == go){
System.out.println("被点击");
}
}
}
在点击Go之后,控制台会输出“被点击字样”
使用方法引用后:
//使用方法引用后
public class LoginJFrame extends JFrame {
public LoginJFrame(){
initJFrame();
initView();
this.setVisible(true);
}
JButton go=new JButton("Go");
private void initView() {
JLabel image=new JLabel();
image.setBounds(100,50,174,174);
image.setBackground(Color.red);
this.getContentPane().add(image);
go.setFont(new Font(null,1,20));
go.setBounds(120,274,150,50);
go.setBackground(Color.WHITE);
//注意这块有区别:
go.addActionListener(this::method);
this.getContentPane().add(go);
}
private void initJFrame() {
this.setTitle("...");
this.setSize(480,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setLayout(null);
this.getContentPane().setBackground(Color.white);
this.setAlwaysOnTop(true);
}
public void method(ActionEvent e) {
Object obj=e.getSource();
if(obj == go){
System.out.println("被点击");
}
}
}
最后结果相同
例 3:父类的引用
public class LoginJFrame extends MyJFrame{
public LoginJFrame(){
initJFrame();
initView();
this.setVisible(true);
}
JButton go=new JButton("Go");
private void initView() {
JLabel image=new JLabel();
image.setBounds(100,50,174,174);
image.setBackground(Color.red);
this.getContentPane().add(image);
go.setFont(new Font(null,1,20));
go.setBounds(120,274,150,50);
go.setBackground(Color.WHITE);
//这里有区别
go.addActionListener(super::method);
this.getContentPane().add(go);
}
private void initJFrame() {
this.setTitle("...");
this.setSize(480,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setLayout(null);
this.getContentPane().setBackground(Color.white);
this.setAlwaysOnTop(true);
}
}
public class MyJFrame extends JFrame {
public void method(ActionEvent e) {
System.out.println("被点击");
}
}
最后输出结果相同
三、引用构造方法
格式:类名 : : new
例 1:
public class Demo1 {
public static void main(String[] args) {
/*
集合里面存储姓名和年龄,比如: 张无忌,15
要求: 将数据封装成Student对象并收集到List集合中
*/
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三,15", "李四,16", "王五,17");
//未引用构造方法
List<Student> newList = list.stream()
.map(s -> new Student
(s.split(",")[0],
Integer.parseInt(s.split(",")[1])))
.collect(Collectors.toList());
System.out.println(newList);
//[Student{name = 张三, age = 15}, Student{name = 李四, age = 16}, Student{name = 王五, age = 17}]
//引用构造方法
List<Student> newList2 = list.stream().map(Student::new)
.collect(Collectors.toList());
System.out.println(newList2);
//[Student{name = 张三, age = 15}, Student{name = 李四, age = 16}, Student{name = 王五, age = 17}]
}
}
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//切割字符串并把对应的数据交到对象中
public Student(String s) {
this.name=s.split(",")[0];
this.age=Integer.parseInt(s.split(",")[1]);
}
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;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
四、其他调用方式
1、使用类名引用成员方法
格式:类名 : : 成员方法
例:
public class StringDemo2 {
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(System.out::println);
//AAA
//BBB
//CCC
//DDD
//引用方法
list.stream().map(String::toUpperCase).forEach(System.out::println);
//AAA
//BBB
//CCC
//DDD
}
}
方法引用的规则:
1、需要有函数式接口
2、被引用的方法必须已经存在
3、被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致
4、被引用方法的功能需要满足当前的需求
抽象方法形参详解:
第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法
在Stream流当中,第一个参数一般都表示流里面的每一个数据
第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的
方法需要是无参的成员方法
2、引用数组的构造方法
格式:数据类型 [ ] : : new
例:
public class Demo2 {
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];
}
});
//使用方法引用
Integer[] arr2 = list.stream().toArray(Integer[]::new);
System.out.println(Arrays.toString(arr));
//[1, 2, 3, 4, 5]
System.out.println(Arrays.toString(arr2));
//[1, 2, 3, 4, 5]
}
}