一、介绍
1. 概念
把已有的方法拿过来用,当做函数式接口中抽象方法的方法体。
2. 使用条件
(1)引用处必须是函数式接口;
(2)被引用的方法必须已经存在;
(3)被引用方法的形参和返回值需要根抽象方法保持一致;
(4)被引用方法的功能要满足当前需求。
注:::是方法引用符
import java.util.Arrays;
import java.util.Comparator;
public class FunctionDemo1 {
public static void main(String[] args) {
// 要求:创建一个数组,进行倒序排序
Integer[] arr = {3, 5, 4, 1, 2, 7};
// 匿名内部类
/*Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(Arrays.toString(arr));*/
// lambda表达式
// 因为第二个参数的类型Comparator是一个函数式接口
/*Arrays.sort(arr, (Integer o1, Integer o2) -> {
return o2 - o1;
});
System.out.println(Arrays.toString(arr));*/
// lambda表达式简化格式
/*Arrays.sort(arr, (o1, o2) -> o2 - o1);
System.out.println(Arrays.toString(arr));*/
// 方法引用
// 1. 引用处需要是函数式接口
// 2. 被引用的方法需要已经存在
// 3. 被引用方法的形参和返回值需要跟抽象方法的形参和返回值类型一致
// 4. 被引用的功能需要能满足当前的要求
// 表示引用FunctionDemo1类里面的subtraction方法
// 把这个方法当作抽象方法的方法体
Arrays.sort(arr, FunctionDemo1::subtraction);
System.out.println(Arrays.toString(arr));
}
// 可以是Java已经写好的,也可以是一些第三方的工具类
public static int subtraction(int num1, int num2) {
return num2 - num1;
}
}
3. 方法引用的分类
(1)引用静态方法
格式:类名::静态方法
范例:Integer::parseInt
练习1:要求:集合中有以下数字,要求把他们都变成int类型。 "1", "2", "3", "4", "5"
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class FunctionDemo2 {
public static void main(String[] args) {
/*
方法引用(引用静态方法)
格式:类名::方法名
要求:集合中有以下数字,要求把他们都变成int类型
"1", "2", "3", "4", "5"
*/
// 1. 创建集合并添加元素
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "1", "2", "3", "4", "5");
// 2. 把他们都变成int类型
/*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)引用成员方法
包含:①引用其他类的成员方法;②引用本类的成员方法;③引用父类的成员方法
格式:对象::成员方法
①其他类:其他类对象::方法名;②本类:this::方法名;③父类:super::方法名
练习1:集合中有一些名字,按照要求过滤数据。
数据:"张无忌", "周芷若", "赵敏", "张强", "张三丰"
要求:只要以“张”开头,而且名字是3个字的
package com.itheima.a01myfunction;
public class StringOperation {
public boolean stringJudge(String s) {
return s.startsWith("张") && s.length() == 3;
}
}
package com.itheima.a01myfunction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
public class FunctionDemo3 {
public static void main(String[] args) {
/*
练习1:集合中有一些名字,按照要求过滤数据。
数据:"张无忌", "周芷若", "赵敏", "张强", "张三丰"
要求:只要以“张”开头,而且名字是3个字的
*/
// 1. 创建集合
ArrayList<String> list = new ArrayList<>();
// 2. 添加数据
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
// 3. 过滤数据
/*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));*/
// 成员方法的引用
StringOperation so = new StringOperation();
list.stream().filter(so::stringJudge)
.forEach(s -> System.out.println(s));
}
}
练习2:GUI界面中点击事件的方法引用写法
// 父类
package com.itheima.a02game;
import javax.swing.*;
import java.awt.event.ActionEvent;
public class MyJFrame extends JFrame {
public void method1(ActionEvent e) {
System.out.println("go按钮被点击了");
}
}
// 子类
package com.itheima.a02game;
import javax.swing.*;
import java.awt.*;
public class LoginJFrame extends MyJFrame {
JButton go = new JButton("Go");
public LoginJFrame() {
//设置图标
setIconImage(Toolkit.getDefaultToolkit().getImage("image\\logo.jpg"));
//设置界面
initJframe();
//添加组件
initView();
//界面显示出来
this.setVisible(true);
}
//添加组件
public void initView() {
JLabel image = new JLabel(new ImageIcon("image\\kit.jpg"));
image.setBounds(100,50,174,174);
this.getContentPane().add(image);
go.setFont(new Font(null,1,20));
go.setBounds(120,274,150,50);
go.setBackground(Color.WHITE);
go.addActionListener(super::method1);
this.getContentPane().add(go);
}
//设置界面
public void initJframe() {
//设置标题
this.setTitle("随机点名器");
//设置大小
this.setSize(400, 500);
//设置关闭模式
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口无法进行调节
this.setResizable(false);
//界面居中
this.setLocationRelativeTo(null);
//取消内部默认居中放置
this.setLayout(null);
//设置背景颜色
this.getContentPane().setBackground(Color.white);
this.setAlwaysOnTop(true);//置顶
}
}
// 启动类
package com.itheima.a02game;
public class App {
public static void main(String[] args) {
new LoginJFrame();
}
}
(3)引用构造方法
格式:类名::new
范例:Student::new
练习:集合里面存储姓名和年龄,比如:张无忌,15。要求:将数据封装成Student对象并收集到List集合中。
// Student类
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 + "}";
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class FunctionDemo4 {
public static void main(String[] args) {
/*
方法引用(引用构造方法)
格式:类名::new
目的:创建这个类的对象
需求:集合里面存储姓名和年龄,要求封装成Student对象并收集到List集合中
*/
//1.创建集合对象
ArrayList<String> list = new ArrayList<>();
//2.添加数据
Collections.addAll(list, "张无忌,15", "周芷若,14", "赵敏,13", "张强,20", "张三丰,100", "张翠山,40", "张良,35", "王二麻子,37", "谢广坤,41");
//3.封装成Student对象并收集到List集合中
//String --> Student
/* 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)使用类名引用成员方法
格式:类名::成员方法
范例:String::substring
练习:集合里面一些字符串,要求变成大写后进行输出。
package com.itheima.a01myfunction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class FunctionDemo5 {
public static void main(String[] args) {
/*
方法引用(类名引用成员方法)
格式:类名::成员方法
需求:集合里面一些字符串,要求变成大写后进行输出。
方法引用的规则:①需要有函数式接口;②被引用的方法必须已经存在;
③被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致;
④被引用方法的功能需要满足当前的需求
抽象方法形参的详解:
第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法。在Stream流中,第一个参数一般都表示流里面的每一个数据
假设流里面的数据都是字符串,那么使用这种方法进行方法调用,只能引用String这个类的给个
第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法
局限性:不能引用所有的成员方法,是跟抽象方法的第一个参数有关,这个参数是什么类型的,只能引用这个类中的方法
*/
// 1. 创建集合对象
ArrayList<String> list = new ArrayList<>();
// 2. 添加数据
Collections.addAll(list, "aaa", "bbb", "ccc", "ddd");
// 3. 变成大写后进行输出
/* 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.print(s + " ")); // AAA BBB CCC DDD
}
}
(5)引用数组的构造方法
格式:数据类型[]::new
范例:int[]::new
练习:集合中存储一些整数,收集到数组当中
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) {
/*
方法引用(数组构造方法)
// 目标:创建一个指定类型的数组
需求:集合中存储一些数据,收集到数组当中
细节:数组的类型,需要跟流中数据的类型保持一致
*/
// 1. 创建集合并添加元素
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5);
// 2. 收集到数组当中
/*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);
// 3. 打印
System.out.println(Arrays.toString(arr2));
}
}
二、综合练习
1. 练习1
集合中存储一些字符串的数据,比如:张三,23。收集到Student类型的数组当中(使用方法引用完成)。
// Student类
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 + "}";
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class FunctionDemo7 {
public static void main(String[] args) {
/*
练习1:集合中存储一些字符串的数据,比如:张三,23。
收集到Student类型的数组当中(使用方法引用完成)。
*/
// 1. 创建集合并添加元素
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌,15", "周芷若,14", "赵敏,13", "张强,20", "张三丰,100", "张翠山,40", "张良,35", "王二麻子,37");
// 2. 先把字符串变成Student对象,然后再把Student对象收集起来
Student[] arr = list.stream().map(Student::new).toArray(Student[]::new);
// 3. 打印数据
System.out.println(Arrays.toString(arr));
}
}
2. 练习2
创建集合添加学生对象,学生对象属性:name, age。只获取姓名并放到数组当中(使用方法引用完成)。
// Student类
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 + "}";
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Function;
public class FunctionDemo8 {
public static void main(String[] args) {
/*
创建集合添加学生对象,学生对象属性:name, age。
只获取姓名并放到数组当中(使用方法引用完成)。
*/
// 1. 创建集合
ArrayList<Student> list = new ArrayList<>();
// 2. 添加元素
list.add(new Student("zhangsan", 23));
list.add(new Student("lisi", 24));
list.add(new Student("wangwu", 25));
// 3. 获取姓名并放到数组当中
/*String[] arr = list.stream().map(new Function<Student, String>() {
@Override
public String apply(Student student) {
return student.getName();
}
}).toArray(String[]::new);
System.out.println(Arrays.toString(arr));*/
String[] arr2 = list.stream().map(Student::getName).toArray(String[]::new);
System.out.println(Arrays.toString(arr2));
}
}
3. 练习3
创建集合添加学生对象,学生对象属性:name, age。把姓名和年龄拼接成:张三-23的字符串,并放到数组当中(使用方法引用完成)。
// Student类
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 name + "-" + age;
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Function;
public class FunctionDemo9 {
public static void main(String[] args) throws FileNotFoundException {
/*
* 需求:
* 创建集合添加学生对象
* 学生对象属性:name,age
* 要求:
* 把姓名和年龄拼接成:张三-23的字符串,并放到数组当中
* 使用方法引用完成
* */
ArrayList<Student> list2 = new ArrayList<>();
list2.add(new Student("zhangsan",23));
list2.add(new Student("lisi",24));
list2.add(new Student("wangwu",25));
/*String[] arr = list2.stream().map(new Function<Student, String>() {
@Override
public String apply(Student student) {
return student.getName() + "-" + student.getAge();
}
}).toArray(String[]::new);
System.out.println(Arrays.toString(arr));*/
String[] arr2 = list2.stream().map(Student::toString).toArray(String[]::new);
System.out.println(Arrays.toString(arr2)); // [zhangsan-23, lisi-24, wangwu-25]
}
}