Lambda表达式&方法引用

Lambda表达式是一个匿名函数,主要是为了简化代码,使代码变的更加简洁紧凑。方法引用可以进一步简化Lambda表达式。


函数式接口

对于函数式接口,我们可以通过lambda表达式来创建该接口的对象

那什么是函数式接口呢?任何接口只包含唯一一个抽象方法,那么它就是一个函数式接口(java官方的函数式接口,一般会使用注解@FunctionalInterface标注)。


Lambda表达式

标准格式

Lambda省去面向对象的条条框框,格式由3个部分组成:

  • 一些参数
  • 一个箭头
  • 一段代码

Lambda表达式的标准格式为:

(参数类型 参数名称) -> { 代码语句 }

格式说明:

  • 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
  • ->是新引入的语法格式,代表指向动作。
  • 大括号内的语法与传统方法体要求基本一致。

看看下边的示例,体会一下lambda表达式的魅力吧。


示例

定义一个函数式接口:

//定义一个函数式接口
interface Say {
    
    
    void sayHello();
}

普通类

我们要使用这个接口,一般是这样的:写一个类然后实现其中的抽象方法

//1.实现类
public class MySay implements Say{
    
    
    @Override
    public void sayHello() {
    
    
        System.out.println("hello!!!");
    }
}

使用:

public class TestLambda {
    
    
    public static void main(String[] args) {
    
    
        Say mySay = new MySay();//1.实现类
        mySay.sayHello();
    }
}

内部类

若这个类只想使用一次,不想单独写在一个文件里,还能不能更加简洁呢?可以的,使用内部类

静态内部类

public class TestLambda {
    
    
    //2.静态内部类
    static class MySay2 implements Say{
    
    
        @Override
        public void sayHello() {
    
    
            System.out.println("hello!!!hello!!!");
        }
    }
    public static void main(String[] args) {
    
    
        mySay = new MySay2();//2.静态内部类
        mySay.sayHello();
    }
}

局部内部类

public class TestLambda {
    
    
    public static void main(String[] args) {
    
    
      //3.局部内部类
        class MySay3 implements Say{
    
    
            @Override
            public void sayHello() {
    
    
                System.out.println("hello!!!hello!!!hello!!!");
            }
        }
        mySay = new MySay3();
        mySay.sayHello();
    }
}

匿名内部类

public class TestLambda {
    
    
    public static void main(String[] args) {
    
    
      mySay = new Say() {
    
    //4.匿名内部类,没有类名,必须借助接口或者父类
            @Override
            public void sayHello() {
    
    
                System.out.println("hello!!!hello!!!hello!!!hello!!!");
            }
        };
        mySay.sayHello();
    }
}

lambda表达式

匿名内部类能怎么写lambda表达式就能怎么写。

注意lambda表达式,需要jdk版本在1.8以上。

public class TestLambda {
    
    
    public static void main(String[] args) {
    
    
      //5.lambda表达式
        mySay = ()-> System.out.println("hello!!!hello!!!hello!!!hello!!!hello!!!");
        mySay.sayHello();
    }
}

使用lambda表达式可以避免匿名内部类定义过多,可以让代码更加简洁只留下核心的逻辑。


省略规则

在Lambda标准格式的基础上,使用省略写法的规则为:

  1. 小括号内参数的类型可以省略;
  2. 如果小括号内有且仅有一个参,则小括号可以省略;
  3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。


方法引用

方法引用可以进一步简化Lambda表达式的写法。

方法引用,使得代码可读性变差,建议掌握Lambda表达式、熟悉方法引用即可。


概述

方法引用使得开发者可以直接引用现存的方法、Java类的构造方法或者实例对象。方法引用和Lambda表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码。


基本使用

方法引用使用一对冒号 ::

下面,我们在 Car 类中定义了 4 个方法作为例子来区分 Java 中 4 种不同方法的引用。

public static class Car {
    
    
    public static Car create( final Supplier< Car > supplier ) {
    
    
        return supplier.get();
    }              

    public static void collide( final Car car ) {
    
    
        System.out.println( "Collided " + car.toString() );
    }

    public void follow( final Car another ) {
    
    
        System.out.println( "Following the " + another.toString() );
    }

    public void repair() {
    
       
        System.out.println( "Repaired " + this.toString() );
    }
}

第一种方法引用的类型是构造器引用,语法是Class::new,或者更一般的形式:Class::new。注意:这个构造器没有参数。

final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );

第二种方法引用的类型是静态方法引用,语法是Class::static_method。注意:这个方法接受一个Car类型的参数。

cars.forEach( Car::collide );

第三种方法引用的类型是某个类的成员方法的引用,语法是Class::method,注意,这个方法没有定义入参:

cars.forEach( Car::repair );

第四种方法引用的类型是某个实例对象的成员方法的引用,语法是instance::method。注意:这个方法接受一个Car类型的参数:

final Car police = Car.create( Car::new );
cars.forEach( police::follow );

示例

静态方法的引用

引用格式:

类名称::静态方法名

案例:

public static void main(String args[]) {
    
    
    List names = new ArrayList();

    names.add("大明");
    names.add("二明");
    names.add("小明");

    //使用foreach遍历集合
    names.forEach(new Consumer() {
    
    
        @Override
        public void accept(Object name) {
    
    
            System.out.println(name);
        }
    });

    //使用lambda表达式简化 匿名内部类
    names.forEach( name ->System.out.println(name) );

    //使用 方法引用 进一步简化
    names.forEach( System.out::println );
}

上面的代码,我们将 System.out::println 方法作为静态方法来引用。

测试结果为:

大明
二明
小明
。。。x3

特定类型方法的引用

特定类型:
string ,任何类型。

格式:

特定类型::方法

注意:
如果第一个参数列表中的形参中的第一个参数作为了后面的方法的调用者,并且其余参数作为后面方法的形参,那么就可以用特定类型方法引用了。

String[] strs = {
    
    "Aaa","Bbb","aaA","Ccc","Ddd","Bbc","Eee","1","5","3","0"};

//排序:默认规则是按照ASCii编码顺序来排序(升序,从小到大),即0-9,A-Z,a-z排序
//Arrays.sort(strs);
//System.out.println(Arrays.asList(strs));//[Aaa, Bbb, Bbc, Ccc, Ddd, Eee, aaA]


//添加比较器,自定义比较规则(忽略大小写)
//Arrays.sort(strs, new Comparator<String>() {
    
    
//    @Override
//    public int compare(String s1, String s2) {
    
    
//        return s1.compareToIgnoreCase(s2);//忽略英文字母大小写
//    }
//});


//使用lambda表达式简化 比较器匿名内部类:
//我们发现接口Comparator,是一个函数式接口,可以使用lambda表达式简化
//Arrays.sort(strs, (s1, s2)-> s1.compareToIgnoreCase(s2) );


//特定类型的方法引用:
//使用 方法引用 进一步简化
Arrays.sort(strs, String::compareToIgnoreCase );


System.out.println(Arrays.asList(strs));//[0, 1, 3, 5, Aaa, aaA, Bbb, Bbc, Ccc, Ddd, Eee]

运行结果:

[0, 1, 3, 5, Aaa, aaA, Bbb, Bbc, Ccc, Ddd, Eee]


函数式编程

函数式编程:



学习自B站遇见狂神说深入学习Java编程-黑马菜鸟教程

猜你喜欢

转载自blog.csdn.net/weixin_44773109/article/details/127810607