第一章 函数式接口
1.1 概念和格式
1.1.1 概念
什么是函数式接口
* 接口中有且只有一个抽象方法则称为函数式接口。
常见的函数式接口
* Runnable,Callable,Comparator,FileFilter
1.1.2 格式
interface 接口名{
返回值类型 方法名(参数列表);
default 返回值类型 方法名(参数列表){
}
}
1.2 @FunctionalInterface注解
* JDK1.8新特性
* 作用:用来修饰接口,告诉编译器该接口是函数式接口,如果不是则会编译失败。
1.3 函数式接口练习
1.3.1 自定义函数式接口(无参无返回)
需求说明
请定义一个函数式接口`Eatable`,内含抽象`eat`方法,没有参数或返回值。使用该接口作为方法的参数,并进而通过
Lambda来使用它
@FunctionalInterface
interface Eatable{
void eat();
}
public class FunctionalInterfaceDemo02 {
public static void main(String[] args){
// 使用匿名内部类调用
testEatable(new Eatable() {
@Override
public void eat() {
System.out.println("吃个蛋...");
}
});
// 使用lambda表达式简化匿名内部类
testEatable(()‐> System.out.println("再吃一个..."));
}
public static void testEatable(Eatable e){
e.eat();
}
}
1.3.2 自定义函数式接口(有参有返回)
需求说明
请定义一个函数式接口`Sumable`,内含抽象`sum`方法,可以将两个int数字相加返回int结果。使用该接口作为方法的
参数,并进而通过Lambda来使用它。
测试代码
@FunctionalInterface
interface Sumable{
int sum(int a,int b);
}
public class FunctionalInterfaceDemo03 {
public static void main(String[] args){
// 使用lambda表达式调用
testSumable((x,y) ‐> x + y);
}
public static void testSumable(Sumable s){
int result = s.sum(1, 2);
System.out.println(result);
}
}
第二章 函数式编程之方法引用
2.1 方法引用的四种类型
2.2.1 静态方法引用
语法格式:
静态方法引用的格式 * 类名::静态方法名 静态方法引用的注意事项 * 被引用方法的参数列表要和函数式接口中抽象方法的参数列表一致。 * 如果函数式接口中的抽象方法有返回值类型,则被引用的方法也必须有相同的返回值类型。 * 如果函数式接口中的抽象方法没有返回值,则被引用的方法可以有返回值也可以没有返回值。
示例代码
@FunctionalInterface
public interface ArrayHelper {
// 返回数组的最大值
int maxValue(int[] arr);
}
/**
数组工具类
*/
public class ArrayUtils {
/**
* 返回数组的最大值
* @param arr 数组
* @return 最大值
*/
public static int getMax(int[] arr){
System.out.println("‐‐‐‐‐‐‐‐‐‐‐");
int maxValue = arr[0];
for (int i = 1; i < arr.length ; i++) {
if (arr[i] > maxValue){
maxValue = arr[i];
}
}
return maxValue;
}
}
public class MethodRefDemo01 {
public static void main(String[] args){
// 定义整型数组
int[] arr = {31,34,3,52,5,6};
// 使用匿名内部类创建ArrayHelper实现类对象
ArrayHelper ah01 = new ArrayHelper(){
@Override
public int maxValue(int[] arr) {
int maxValue = arr[0];
for (int i = 1; i < arr.length ; i++) {
if (arr[i] > maxValue){
maxValue = arr[i];
}
}
return maxValue;
}
};
// 调用方法获得数组的最大值
int maxValue01 = ah01.maxValue(arr);
System.out.println(maxValue01);
// 使用lambda表达式简化匿名内部类
ArrayHelper ah02 = array ‐> {
int maxValue = arr[0];
for (int i = 1; i < arr.length ; i++) {
if (arr[i] > maxValue){
maxValue = arr[i];
}
}
return maxValue;
};
// 调用方法获得数组的最大值
int maxValue02 = ah02.maxValue(arr);
System.out.println(maxValue02);
// 在lambda表达式中调用工具类已经存在的方法
ArrayHelper ah03 = array ‐> ArrayUtils.getMax(array);
// 调用方法获得数组的最大值
int maxValue03 = ah03.maxValue(arr);
System.out.println(maxValue03);
// 当lambda表达式中仅仅调用了一个已经存在的方法时,可以考虑使用方法引用简化lambda表达式
/*
ArrayHelper ah04 = ArrayUtils::getMax; 等价下面代码:
1. 创建函数式接口的匿名内部类对象
ArrayHelper ah04 = new ArrayHelper(){
int maxValue(int[] arr){
// 2.调用被引用的方法
return ArrayUtils.getMax(arr);
}
}
int maxValue04 = ah04.maxValue(arr);
*/
ArrayHelper ah04 = ArrayUtils::getMax;
// 调用方法获得数组的最大值
int maxValue04 = ah04.maxValue(arr);
System.out.println(maxValue04);
}
}
2.2.2 对象方法引用
语法格式:
对象方法引用的格式
* 对象名::非静态方法名
对象方法引用的注意事项
* 被引用方法的参数列表要和函数式接口中抽象方法的参数列表一致。
* 如果函数式接口中的抽象方法有返回值类型,则被引用的方法也必须有相同的返回值类型。
* 如果函数式接口中的抽象方法没有返回值,则被引用的方法可以有返回值也可以没有返回值。
示例代码
@FunctionalInterface
public interface NumHelper {
// 获得a到b之间的随机数
int nextAToB(int a,int b);
}
public class MyRandom {
// 返回a到b之间的随机数,比如 a = 100,b == 200 返回100到200之间的随机数
public int nextIntAToB(int a,int b){
// 创建随机数对象
Random r = new Random();
return r.nextInt(b ‐ a + 1) + a;
}
}
public class MethodRefDemo01 {
public static void main(String[] args){
// 使用匿名内部类创建NumHelper接口实现类对象
NumHelper nh01 = new NumHelper(){
@Override
public int nextAToB(int a, int b) {
// 创建随机数对象
Random r = new Random();
return r.nextInt(b ‐ a + 1) + a;
}
};
// 获得100到200之间的随机数
int num01 = nh01.nextAToB(100, 200);
System.out.println(num01);
// 使用lambda表达式简化匿名内部类
NumHelper nh02 = (a,b) ‐>{
// 创建随机数对象
Random r = new Random();
return r.nextInt(b ‐ a + 1) + a;
};
// 获得200到300之间的随机数
int num02 = nh02.nextAToB(200, 300);
System.out.println(num02);
// 创建MyRandom类对象
MyRandom myRandom = new MyRandom();
// 在lambda表达式中调用已经存在的方法
NumHelper nh03 = (a,b) ‐> myRandom.nextIntAToB(a, b);
// 获得300到400之间的随机数
int num03 = nh03.nextAToB(300, 400);
System.out.println(num03);
// 使用方法引用简化lambda表达式
/*
NumHelper nh04 = myRandom::nextIntAToB; 等价下面代码:
1. NumHelper nh04 = new NumHelper(){
int nextAToB(int a,int b){
// 2. 调用被引用的方法
return myRandom.nextIntAToB(a,b);
}
}
*/
NumHelper nh04 = myRandom::nextIntAToB;
// 获得400到500之间的随机数
int num04 = nh04.nextAToB(400, 500);
System.out.println(num04);
}
}
2.2.3 类构造方法的引用
语法格式
构造方法引用的格式
* 类名::new
构造方法引用注意事项
* 被引用的类必须存在一个构造方法的参数列表和函数式接口中的抽象方法参数列表相同
示例代码:
public class MethodRefDemo01 {
public static void main(String[] args){
// 使用匿名内部类创建CarFactory接口实现类对象
CarFactory cf01 = new CarFactory(){
@Override
public Car makeCar(String brand) {
return new Car(brand);
}
};
// 生产一部宝马车
Car bmw = cf01.makeCar("宝马");
System.out.println(bmw);
// 使用lambda表达式简化匿名内部类
CarFactory cf02 = brand ‐> new Car(brand);
// 生产一部奥迪
Car audi = cf02.makeCar("奥迪");
System.out.println(audi);
// 使用方法引用简化lambda表达式
/*
CarFactory cf03 = Car::new; 等价下面代码
CarFactory cf03 = new CarFactory(){
Car makeCar(String brand){
return new Car(brand);
}
}
*/
CarFactory cf03 = Car::new;
// 生产一部红旗
Car hq = cf03.makeCar("红旗");
System.out.println(hq);
}
}
2.2.4 数组构造方法引用
语法格式:
数据类型[]::new
示例代码
@FunctionalInterface
interface ArrayBuilder{
// 创建长度为length的整型数组
int[] buildArray(int length);
}
public class MethodRefDemo02 {
public static void main(String[] args){
// 使用lambda表达式创建接口实现类对象
ArrayBuilder ab01 = length ‐> new int[length];
// 创建长度为10的数组
int[] arr01 = ab01.buildArray(10);
System.out.println(Arrays.toString(arr01));
// 使用方法引用简化lambda表达式
ArrayBuilder ab02 = int[]::new;
// 创建长度为20的数组
int[] arr02 = ab02.buildArray(20);
System.out.println(Arrays.toString(arr02));
}
}
2.2.5 特定类型的实例方法引用
语法格式
特定类型的实例方法引用格式
* 类名::非静态方法
特定类型的实例方法注意事项
* 被引用的方法要比函数式接口中的抽象方法要少一个参数。
* 函数式接口中的抽象方法参数列表的第一个参数调用被引用的方法,
抽象方法中的其他参数(除了第一个参数以外的其他参数)作为被引用方法的参数传递
示例代码
public class MethodRefDemo01 {
public static void main(String[] args){
String[] stringsArray = {"AA", "James", "Mary",
"John", "Patricia", "Robert", "aa", "Linda"};
/*// 使用匿名内部类创建比较器对象: 对字符串数组排序,忽略大小写
Arrays.sort(stringsArray, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
});*/
// 使用lambda表达式创建比较器对象: 对字符串数组排序,忽略大小写
Arrays.sort(stringsArray,(o1,o2)‐> o1.compareToIgnoreCase(o2));
// 使用方法引用简化lambda表达式
/*
String::compareToIgnoreCase 等价下面代码:
1. 创建匿名内部类对象
new Comparator(){
public int compare(String o1,String o2){
// 2.调用被引用的方法
return o1.compareToIgnoreCase(o2);
}
}
*/
Arrays.sort(stringsArray,String::compareToIgnoreCase);
for (String str : stringsArray) {
System.out.println(str);
}
}
}