1.Lambda表达式

JDK8开始新增的语法形式,用于简化匿名内部类的代码写法。

格式:(被重写的形参列表)->{被重写的方法体代码}

注意事项:Lambda表达式并不是说能简化全部匿名类的写法,只能简化函数式接口的匿名内部类。函数式接口指的是首先是个接口,然后接口里面只能有一个抽象方法。函数式接口会写出@FunctionalInterface

例子:

package com.lzk.test;

import java.util.Arrays;
import java.util.Comparator;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntUnaryOperator;

public class test {
    public static void main(String[] args) {
        // 使用匿名内部类创建Animal对象并实现run方法
//        Animal a = new Animal() {
//            @Override
//            public void run() {
//                System.out.println("狗跑的贼快~~");
//            }
//        };
//        a.run();1
//        ----------------------------------------------------------------------------------------
//        注意:Lambda表达式并不是说能简化全部匿名类的写法,只能简化函数式接口的匿名内部类。下面这个用的是抽象类
//        Animal a = () -> {
//            System.out.println("猫跑的也很快~~");
//        }
//    };
//        a.run();
//
//        ------------------------------------------------
            Swimming s = new Swimming() {
                @Override
                public void swim() {
                    System.out.println("鱼游泳的也很快~~");
                }
            };
            s.swim();
//            上下两者一样
            Swimming s1 = () -> {
                System.out.println("鸟飞的也很快~~");
            };
            s1.swim();
            }
    }
interface Swimming {
        void swim();
}
    // 抽象类Animal
    abstract class Animal {
        public abstract void run();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.

进一步的省略写法

(1)参数类型可以不写

(2)如果只有一个参数,参数类型可以省略,同时()也可以省略。

(3)如果Lambda表示式中的方法体代码只有一行代码,可以省略大括号不写,同时省略分号!!此时如果这行代码是return语句,也必须去掉return不写。

GreetingService greetService1 = ( message) -> {
    System.out.println(message);
};

// 只有一个参数,参数类型可以省略,同时也可以省略括号
GreetingService greetService2 = message -> {
    System.out.println(message);
};

// 方法体只有一行代码,可以省略大括号不写,同时省略分号
GreetingService greetService3 = message -> System.out.println(message);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

2.方法引用::

 (1)静态方法的引用

如果某个Lambda表达式里只是调用一个静态方法,并且前后参数一致,就可以使用静态方法引用。

public class test {
    public static void main(String[] args) {
        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精", 169.5, 23);
        students[1] = new Student("紫霞", 163.8, 26);
        students[2] = new Student("紫霞", 163.8, 26);
        students[3] = new Student("至尊宝", 167.5, 24);

        // 原始写法:使用匿名内部类进行排序
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();
            }
        });

        // 使用Lambda简化的形式
        Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());

        // 静态方法引用
        Arrays.sort(students, CompareByData::compareByAge);


    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

静态方法

public class CompareByData {
    public static int compareByAge(Student o1, Student o2){
        return o1.getAge() - o2.getAge();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

(2)实例方法引用

如果某个Lambda表达式里只是调用一个实例方法,并且前后参数一致,就可以使用实例方法引用。

Arrays.sort(students, (o1, o2) -> o2.getAge() - o1.getAge());
       
       CompareByData compare = new CompareByData();
        Arrays.sort(students, (o1, o2) -> compare.compareByAgeDesc(o1, o2));
//        实例方法引用
        Arrays.sort(students,compare::compareByAgeDesc);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

实例方法

public class CompareByData {
    public int compareByAgeDesc(Student o1, Student o2){
        return o2.getAge() - o1.getAge();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

(3)特定类型的方法引用

如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数作为方法的主调,后面的参数都是作为该实例方法的入参的,此时就可以使用特定类型的方法引用。

public class test {
    public static void main(String[] args) {
        String[] names = {"Andy", "angela", "Bob", "bob", "Charles", "charles"};

        // 原始写法:使用匿名内部类进行排序
        Arrays.sort(names, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 制定比较规则,o1 = "Andy" o2 = "angela"
                return o1.compareToIgnoreCase(o2);
            }
        });

        // Lambda表达式
        Arrays.sort(names, (o1, o2) -> o1.compareToIgnoreCase(o2));

        // 特定类型的方法引用
        Arrays.sort(names, String::compareToIgnoreCase);

        // 输出排序后的数组
        System.out.println(Arrays.toString(names));
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

(4)构造器引用(理解语法)

public class test {
    public static void main(String[] args) {
        // 使用匿名内部类实现CreateCar接口
        CreateCar cc = new CreateCar() {
            @Override
            public Car create(String name, double price) {
                return new Car(name, price);
            }
        };
        Car car1 = cc.create("奥迪", 49.9);
        System.out.println(car1);


       
        // 使用Lambda表达式实现CreateCar接口
        CreateCar cc2 = (name, price) -> new Car(name, price);
        Car car2 = cc2.create("宝马", 59.9);
        System.out.println(car2);

        // 使用构造器引用实现CreateCar接口
        CreateCar cc3 = Car::new;
        Car car3 = cc3.create("奔驰", 69.9);
        System.out.println(car3);
    }
    interface CreateCar {
        Car create(String name, double price);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.

构造器

package com.lzk.test;

public class Car {
    private String name;
    private double price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public Car() {
    }

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }
    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.