学习任务:

视频学习

理解传递代码的需求

动手测试Lambda实现代码的传递

Lambda表达式语法格式

下边的程序是对一个一维整型数组进行排序,仔细阅读程序理解程序优化的需求:

package com.pbteach.javase.oop.lambda.test1;

/**
 * 	数组冒泡排序
 * @author 攀博课堂(www.pbteach.com)
 *
 */
public class ArraySortDemo1 {

	public static void main(String[] args) {
    	//定义一个int数组并手动初始化
    	int[] datas = {7,8,7,6,5,4,3,4};
    	System.out.println("开始排序...");
    	sort(datas);
    	//遍历数组并输出数组元素
    	for(int i=0;i<datas.length;i++) {
    		System.out.println(datas[i]);
    	}
    }
	public static void sort(int[] datas) {
		for (int i = 0; i < datas.length; i++) {
            for (int j = i + 1; j < datas.length; j++) {
                if(datas[i]>datas[j]){
                    int temp = datas[i];
                    datas[i] = datas[j];
                    datas[j] = temp;
                }
            }
        }

}

本代码使用冒泡排序方法对数组完成升序排列,如果要改为降序排列如何实现?

1)首先分析升、降序排序的方法

拿前后两个元素进行比较,前边的元素大于后边的元素则交换位置,最终完成升序排序。

前边的元素小于后边的元素则交换位置,最终完成降序排序。

总结:

升序:前边的元素大于后边的元素则交换位置

降序:前边的元素小于后边的元素则交换位置

2)在只写一个sort方法的前提下讨论实现方法

升序还是降序的关键代码是:if(datas[i]>datas[j])

如果if中是datas[i]>datas[j]则为升序,如果是datas[i]<datas[j]则为降序。

如何用一个方法实现灵活的排序规则呢?

下边用几个方案来实现,并分析每个方案的问题点,根据问题点进一步优化。

方案1:sort方法增加一个参数来控制是降序还是升序。

如下代码:

使用sortType来控制升、降序,为true表示升序,为false表示降序。

   /**
	 * 	排序方法
	 * @param datas
	 * @param sortType 为true表示升序,为false表示降序
	 */
	public static void sort(int[] datas,boolean sortType) {
		for (int i = 0; i < datas.length; i++) {
            for (int j = i + 1; j < datas.length; j++) {
                if(sortType){
                    if(datas[i]>datas[j]){
                        int temp = datas[i];
                        datas[i] = datas[j];
                        datas[j] = temp;
                    }
                }else{
                    if(datas[i]<datas[j]){
                        int temp = datas[i];
                        datas[i] = datas[j];
                        datas[j] = temp;
                    }
                }

            }
        }
	}

测试代码:

	public static void main(String[] args) {
    	//定义一个int数组并手动初始化
    	int[] datas = {7,8,7,6,5,4,3,4};
    	System.out.println("开始排序...");
    	sort(datas,true);//升序
    	sort(datas,false);//降序
    	//遍历数组并输出数组元素
    	for(int i=0;i<datas.length;i++) {
    		System.out.println(datas[i]);
    	}
    }

方案1的缺点是:冗余代码较多,代码不够清晰。

方案2:将前后元素的比较代码抽取到一个接口

接口如下:

package com.pbteach.javase.oop.lambda.test1;

/**
 * 	排序比较接口
 * @author 攀博课堂(www.pbteach.com)
 *
 */
public interface SortCompare {

	boolean compare(int a,int b);
}

定义两个接口实现类,如下:

package com.pbteach.javase.oop.lambda.test1;

/**
 * 	排序比较接口实现
 * @author 攀博课堂(www.pbteach.com)
 *
 */
public class SortCompareImpl implements SortCompare {

	@Override
	public boolean compare(int a, int b) {
		return a>b;
	}

}

/**
 * 	排序比较接口实现
 * @author 攀博课堂(www.pbteach.com)
 *
 */
public class SortCompareImpl2 implements SortCompare {

	@Override
	public boolean compare(int a, int b) {
		return a<b;
	}
  
}

改造sort方法:

	/**
	 *	排序方法
	 * @param datas
	 * @param sortCompare 排序接口
	 */
	public static void sort(int[] datas,SortCompare sortCompare) {
		for (int i = 0; i < datas.length; i++) {
            for (int j = i + 1; j < datas.length; j++) {
                if(sortCompare.compare(datas[i],datas[j])){
                    int temp = datas[i];
                    datas[i] = datas[j];
                    datas[j] = temp;
                }
            }
        }
	}

测试代码:

	public static void main(String[] args) {
    	//定义一个int数组并手动初始化
    	int[] datas = {7,8,7,6,5,4,3,4};
    	System.out.println("开始排序...");
    	sort(datas,new SortCompareImpl());//升序
    	sort(datas,new SortCompareImpl2());//降序
    	//遍历数组并输出数组元素
    	for(int i=0;i<datas.length;i++) {
    		System.out.println(datas[i]);
    	}
    }

方案2的缺点:实现起来繁琐,为了封装一行比较代码需要定义一个类,如果要实现降序还要实现一个接口实现类。

方案3:使用匿名内部类实现比较接口

使用匿名内部类可以省去定义类的繁琐,如下代码:

	public static void main(String[] args) {
    	//定义一个int数组并手动初始化
    	int[] datas = {7,8,7,6,5,4,3,4};
    	System.out.println("开始排序...");
    	//升序
    	sort(datas,new SortCompare() {
			
			@Override
			public boolean compare(int a, int b) {
				return a>b;
			}
		});
		//降序
    	sort(datas,new SortCompare() {
			
			@Override
			public boolean compare(int a, int b) {
				return a<b;
			}
		});
    	//遍历数组并输出数组元素
    	for(int i=0;i<datas.length;i++) {
    		System.out.println(datas[i]);
    	}
    }

方案3比方案2的实现更加简洁、易读。

进行到这里其实我们的需求是为了传递一块代码,即两个数比较的代码。

使用匿名内部类的方案虽然比前边的方法简洁,但是为了传递一行代码也需要定义很多无关的代码,还是有些繁琐。

从Java8开始新增了Lambda表达式,它是一种匿名内部类的简化实现方式,下边是使用Lambda表达式实现排序的代码:

public static void main(String[] args) {
    	//定义一个int数组并手动初始化
    	int[] datas = {7,8,7,6,5,4,3,4};
    	System.out.println("开始排序...");
    	sort(datas,(a,b)->a>b);//升序
    	sort(datas,(a,b)->a<b);//降序
    	//遍历数组并输出数组元素
    	for(int i=0;i<datas.length;i++) {
    		System.out.println(datas[i]);
    	}
    }

代码中(a,b)->a>b和(a,b)->a<b都是Lambda表达式,sort(datas,(a,b)->a>b);语句将Lambda表达式(a,b)->a>b 传递给sort方法的参数sortCompare,所以(a,b)->a>b是SortCompare接口类型的一个对象。见下图:

image-20201003182625880

将Lambda改为(a,b)->a<b,此时实现了数组的降序排序。

Lambda表达式实现了匿名内部类的功能,但它的语法格式却有很大的不同,语法如下:

(参数类型 参数名称) -> { 方法体代码 }

共由3个部分组成:

1)参数列表

参数列表与接口中所定义的方法参数列表一致,如果没有参数则只写一个小括号,多个参数之间以逗号分隔。

2)箭头

->是java新引入的语法格式,指向动作即做什么。

3)方法体代码

大括号内的语法与传统方法体要求基本一致 。

根据Lambda的语法对应到匿名内部类,如下图:

image-20210623200052867

(a,b)为参数列表,共两个参数,参数中间用逗号分隔;a>b为方法体,这里犹豫只有一条语句所以就没有使用大括号,稍后详细介绍Lambda的写法。

提问-攀博课堂
我要提问 不会就问,有效沟通
关注公众号,加入微信群交流提问。 攀博课堂官方公众号
问答列表,查看本知识点所有问题