JAVASE进阶:函数式编程——lambda表达式替代匿名内部类

‍作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
上期文章:JAVASE进阶:强推!源码分析——字符串拼接底层原理、StringBuilder底层原理
订阅专栏:JAVASE进阶
希望文章对你们有所帮助

lambda表达式,高级程序员写起来真的是信手拈来,而且他们经常是把lambda放在Collection大类里面的,所以应该要把知识点先学牢。

当要对数组进行逆序排序的时候,可以用匿名内部类,可能会写成:

public class ArrayTest {
    public static void main(String[] args) {
        Integer[] arr = {2, 3, 1, 5, 6, 8, 4};
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.println(Arrays.toString(arr));
    }
}

这种写法其实并不是太便捷,而lambda就可以便捷我们的写法。在此之前先把匿名内部类知识再简单过一下。

lambda表达式替代匿名内部类

  • 内部类
    • 匿名内部类
  • lambda表达式
    • 函数式编程
    • lambda表达式
    • lambda表达式省略规则
  • lambda表达式练习

内部类

类的五大成员:属性、方法、构造方法、代码块、内部类。
其使用场景其实还是很广泛的,例如现在写一个Javabean类来描述汽车:

public class Car{
	String name;
	int carAge;
	int carColor;
	String engineName;
	int engineAge;
}

但是实际上,引擎是独立于车的,不应该成Car这个类的属性。所以应该把engineName和engineAge单独写一个类,但是写在外部,车的引擎自己本身又没有什么作用,所以看起来最完美的是写在Car的内部,表示车里面有发动机,而发送机也是一个独立个体,即:

public class Car{
	String name;
	int carAge;
	int carColor;
	
	class Engine{
		String engineName;
		int engineAge;
	}
}

访问特点:内部类可以直接访问外部类成员(包括私有),外部类要访问内部类必须创建对象。

内部类分为4大类:成员内部类、静态内部类、局部内部类以及匿名内部类。其中匿名内部类我们才会经常使用,前面的几个内部类一般我也就是在读源码的时候有见到过,所以暂时没必要理会。

访问的时候,内部类的方法可以用变量调用局部变量,用this.变量调用本内部类的成员变量,用Outer.this.a调用外部类的成员变量。

匿名内部类

匿名内部类本质上就是隐藏了名字的内部类。包含了继承/实现、方法重写、创建对象,格式:

new 类名或接口名(){
	重写方法;
};

这样的方式可以大大简化我们的代码。可以看下面的例子:

public interface Swim{
	public abstract void swim();
}

这个方法如果要重写,可以写一个具体的类,例如:

public class Student implements Swim{
	@Override
	public void swim(){...}
}

接着在main函数中,需要先创建Student对象,再调用方法。而有了匿名内部类,我们无须Student类就可以重写方法。这个类是没有具体的名字了,但是实际上它还是个类,是类就可以创建对象,要创建这个没有名字的类的对象,可以这么写:

new Swim(){
	@Override
	public void swim(){...}
}

注意上面整体是对象,这个对象对应的类没有名字,只是实现了Swim接口。
所以想要调用里面的swim方法时,可以直接写成:

new Swim(){
	@Override
	public void swim(){...}
}.swim();

lambda表达式

在最开头写了如何对数组进行逆序的排序,直接调用Arrays里面的sort方法,并把排序规则写成o2-o1就好了,而使用lambda表达式,排序过程可以简化为:

public class ArrayTest {
    public static void main(String[] args) {
        Integer[] arr = {2, 3, 1, 5, 6, 8, 4};
        Arrays.sort(arr, (o1, o2) -> o2 - o1);
        System.out.println(Arrays.toString(arr));
    }
}

看起来真的是爽,这其实是一种函数式编程的思想特点。

函数式编程

函数式编程就是一种思想特点,和面向对象是不太一样的。

面向对象是先找到对象,再让对象做事情,匿名内部类写的排序规则就是先创建了Comparator对象,在里面重写了排序的规则,sort函数就调用了这种规则。
这种写法之所以麻烦,是因为sort函数根本不在乎你是哪个对象,它需要的只是重写方法里面的规则,之前就是因为受限于面向对象的原则,所以才写的这么麻烦。

而函数式编程就可以忽略面向对象的复杂语法,强调做什么,而不是谁去做。而lambda表达式其实就是函数式编程思想的体现。

lambda表达式

lambda表达式是JDK8开始后的一种新语法形式,格式:

() -> {

}

():方法的形参
->:固定格式
{}:方法的方法体

注意:lambda表达式可以简化匿名内部类的书写,但是不是所有匿名内部类都可以用lambda表达式来简化。
lambda表达式只能简化函数式接口的匿名内部类的写法,其中函数式接口指的是有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以加@FunctionalInterface,如果满足这个要求,则@FunctionalInterface是不会报错的。

lambda作为一个匿名函数,可以把lambda表达式理解成是一段可传递的代码,它可以写出更简洁、更灵活的代码,作为一种更紧凑的代码风格,使Java语言表达能力得到了提升。

lambda表达式省略规则

前面演示lambda表达式,其实是最精简版本的,而朴素版本是这样的:

Arrays.sort(arr, (Integer o1, Integer o2) -> {
	return o2 - o1;
});

lambda省略规则:

1、参数类型可以不写
2、若只有一个参数,可以直接省略"()"
3、若lambda方法体只有一行,则不用写"{}“、“return”、”;",但是必须同时省略。

lambda表达式练习

很容易的知识点,学了就会做。

对于一个字符串数组,对其长度进行从长到短排序:
1、匿名内部类:

	public static void main(String[] args) {
        String[] arr = {"a", "aaaa", "aaa", "aa"};
        Arrays.sort(arr, new Comparator<String>(){
            @Override
            public int compare(String o1, String o2) {
                return o2.length() - o1.length();
            }
        });
        System.out.println(Arrays.toString(arr));
    }

2、lambda表达式:

	public static void main(String[] args) {
        String[] arr = {"a", "aaaa", "aaa", "aa"};
        Arrays.sort(arr, (o1, o2) -> o2.length() - o1.length());
        System.out.println(Arrays.toString(arr));
    }

你可能感兴趣的:(JAVASE进阶,java,lambda,函数式编程,面试)