JDK1.8的新特性之Lambda表达式

Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

1.如何书写Lambda的表达式

MyInterface接口(提供show方法):

public interface MyInterface {
    void show();
}

测试类:

public class MyTest {
    public static void main(String[] args) {
        // Lambda 表达式,是JDK1.8之后,提供一种语法风格,你可以认为他是匿名内部类的一种进行形式,他可以作为参数进行传递

        //匿名内部类
        MyInterface myInterface = new MyInterface() {
            @Override
            public void show() {
                System.out.println("这是show方法");
            }
        };

        //针对上面的匿名内部类的写法,我们可以使用 Lambda 表达式 进行简化

        MyInterface myInterface2 = () -> {
            System.out.println("这是show方法");
        };
    }
}


2.Lambda的表达式的近一步简写

public class MyTest2 {
    public static void main(String[] args) {
        //Lambda 表达式,的语法
        //引入一个箭头符号  ->
        // 箭头 -> 把 Lambda 表达式 分成左右两部分
        // 箭头左边是 接口中抽象方法的 形参列表
        // 箭头右边是,抽象方法的具体重写逻辑

        // 匿名内部类的写法
        Comparator comparator = new Comparator() {

            @Override
            public int compare(Integer a, Integer b) {
                return a - b;
            }
        };

        //第一步简写:
        Comparator comparator2 = (Integer a, Integer b) -> {
            return a - b;
        };
        //形参的数据类型,可以省略不写,因为有泛型可以推断出形参的数据类型

        Comparator comparator3 = (a, b) -> {

            return a - b;
        };

        //还能再简化
        //如果你的重写逻辑只有一行代码,那么{} return 都可以省略不写
        Comparator comparator4 = (a, b) -> a - b;
   }
}


3.匿名内部类有参数传递时Lambda的表达式的写法

Iiterface接口:

public interface Iinterface {
    int test(int num);
}

测试类:

public class MyTest2 {
    public static void main(String[] args) {
        Iinterface iinterface = new Iinterface() {

            @Override
            public int test(int num) {
                return num + 10;
            }
        };

        Lambda 表达式,简写了匿名内部类 ,如果形参只有一个 ()可以省略不写
        Iinterface iinterface2 = x -> x += 10;
    }
}


4.匿名内部类做为参数传递和Lambda表达式作为参数来传递

public class MyTest3 {
    public static void main(String[] args) {
        TreeSet strings = new TreeSet<>(new Comparator() {
            @Override
            public int compare(String a, String b) {
                return 0;
            }
        });


        TreeSet strings2 = new TreeSet<>((a, b) -> a.compareTo(b));

        //可以alt+enter 选择替换成 Lmabda表达式
        TreeSet strings3 = new TreeSet<>((a, b) -> a.compareTo(b));
    }
}


5.函数式接口的定义是: 只包含一个抽象方法的接口,称为函数式接口。

任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.

下面代码加上注解就会报错:

//@FunctionalInterface 加上就报错
public interface HeHe {
    void aa();

    void bb();
}

函数式接口:

@FunctionalInterface //这个注解就表明了,这是一个函数式接口
public interface HaHa {
    void test();
}

测试类:

public class MyTest {
    public static void main(String[] args) {
        //Lambda 表达式 他需要函数式接口的支持,换句话说,就是只有函数式接口,才能使用Lambda写出来
        // 函数式接口:就是接口中,只有一个抽象方法,有个注解 @FunctionalInterface 可以检测该接口是不是函数式接口

        HeHe heHe = new HeHe() {

            @Override
            public void aa() {

            }

            @Override
            public void bb() {

            }
        };


        HaHa haHa = new HaHa() {

            @Override
            public void test() {

            }
        };

        HaHa haHa2 = () -> System.out.println("aaaa");

    }
}


6.Java中提供的4大核心函数式接口

函数式接口

参数类型

返回类型

用途

Consumer

消费型接口

T

void

对类型为T的对象应用操
作,包含方法:
void accept(T t)

Supplier

供给型接口

T

返回类型为T的对象,包
含方法: T get();

Function

函数型接口

T

R

对类型为T的对象应用操
作,并返回结果。结果
是R类型的对象。包含方
法: R apply(T t);

Predicate 断言型接口

T

boolean

确定类型为T的对象是否
满足某约束,并返回
boolean 值。包含方法
boolean test(T t);

其他函数式接口:

函数式接口

参数类型

返回类型

用途

BiFunction

T U

R

对类型为 T, U 参数应用
操作, 返回 R 类型的结
果。 包含方法为
R apply(T t, U u);

UnaryOperator

(Function的子接口)

T

T

对类型为T的对象进行一
元运算, 并返回T类型的
结果。 包含方法为
T apply(T t);

BinaryOperator

(BiFunction的子接口)

T T

T

对类型为T的对象进行二
元运算, 并返回T类型的
结果。 包含方法为
T apply(T t1, T t2);

BiConsumer

T U

void

对类型为T, U 参数应用
操作。 包含方法为
void accept(T t, U u)

ToIntFunction
ToLongFunction
ToDoubleFunction

T

int
long
double

分 别 计 算 int 、 long 、
double、 值的函数

IntFunction
LongFunction
DoubleFunction

int
long
double

R

参数分别为int、 long、
double 类型的函数


7.方法引用:

方法引用:方法引用其实是Lambda表达式的另一种写法,
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用.
注意:实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:使用操作符 “ ::” 将方法名和对象或类的名字分隔开来。


如下三种主要使用情况:

对象::实例方法
 类::静态方法
 类::实例方法

public class MyTest {
    public static void main(String[] args) {
        Consumer consumer = new Consumer() {

            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("abc");

        Consumer consumer2 = s -> System.out.println(s);
        consumer2.accept("hello");


        //你对 Consumer接口 中的  public void accept(String s) 这抽象方法的重写逻辑 System.out.println(s)
        //注意观察:accept(String s) 这抽象方法,没有返回值,有一个参数
        //再来观察:我们的重写逻辑
        //PrintStream out = System.out;
        //out.println("abc");
        //调用的这个println("abc") 他的返回值类型和形参列表,跟 accept(String s) 方法的返回值类型和形参列表是一致的,如果有这种巧合就可以简写成下面的  实例对象::方法
        Consumer consumer3 = System.out::println;


        System.out.println("==========================");

        BinaryOperator binaryOperator = new BinaryOperator() {

            @Override
            public Double apply(Double x, Double y) {
                return Math.max(x, y);
            }
        };

        //第一次简写
        BinaryOperator binaryOperator2 = (x, y) -> Math.max(x, y);

        //最终简写,因为又有巧合重写
        //观察: BinaryOperator 中的 apply抽象方法,有一个返回值,有两个参数
        //观察我们的重写逻辑  Math.max(x, y); 调用 的max方法,有一个返回值,有两个参数,能和apply抽象方法对应上

        //最终简写,类名::静态方法
        BinaryOperator binaryOperator3 = Math::max;

        System.out.println("==============================================");

        Comparator comparator = new Comparator() {

            @Override
            public int compare(String a, String b) {
                //第一个参数作为了调用者,第二个参数,作为传入值
                return a.compareTo(b);
            }
        };
        //第一步简写
        Comparator comparator2 = (a, b) -> a.compareTo(b);

        //最终简写:第一个参数作为了调用者,第二个参数,作为传入值
        Comparator comparator3 = String::compareTo;


        System.out.println("=========================================");

        BiFunction biFunction = new BiFunction() {

            @Override
            public Boolean apply(String x, String y) {
                return x.equals(y);
            }
        };

        BiFunction biFunction2 = (x, y) -> x.equals(y);

        //最终简写
        BiFunction biFunction3 = String::equals;

    }
}


8.构造器引用:

格式:ClassName::new

与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!

Student类:

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试类:

public class MyTest2 {
    public static void main(String[] args) {
        Supplier supplier = new Supplier() {

            @Override
            public Student get() {
                return new Student();
            }
        };

        Supplier supplier2 = () -> new Student();

        //最终简写 观察:构造方法,和接口中的抽象方法get() 方法的返回值和形参列表能对应上,就可以用构造引用简写

        Supplier supplier3 = Student::new;
        System.out.println("==================================================");

        BiFunction biFunction = new BiFunction() {

            @Override
            public Student apply(String name, Integer age) {
                return new Student(name, age);
            }

        };
        Student wangwu = biFunction.apply("wangwu", 25);
        //第一次简写
        BiFunction biFunction2 = (name, age) -> new Student(name, age);
        Student s0 = biFunction2.apply("lisi", 24);
        //最终简写:

        BiFunction biFunction3 = Student::new;

        Student s = biFunction3.apply("张三", 23);

    }
}

你可能感兴趣的:(java,开发语言,后端)