Lambda表达式
Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码向数据一样进行传递),可以写出更简洁,更灵活的代码,作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
//Lambda表达式,是匿名内部类的一种简写形式。
MyInterface myInterface = () -> {
System.out.println("show");
};
//Lambda表达式的语法特点
//1.Lambda表达式 引入了一个箭头符号 ->
//2.箭头符号 -> 把Lambda表达式分成左右两部分
//3.左边:写这个接口中的抽象方法的形参列表。
//4.右边:你对这个接口中的抽象方法的具体的重写逻辑
public interface MyInterface {
public int test(String name, int age);
}
MyInterface myInterface = new MyInterface() {//抽象类需要重写
@Override
public int test(String name, int age) {
System.out.println(name + "==" + age);
return 100;
}
};
//第一步简写
MyInterface myInterface2 = (String name, int age) -> {
System.out.println(name + "==" + age);
return 100;
};
//第二步简写 形参的数据类型也可以省略不写
MyInterface myInterface3 = (name, age) -> {
System.out.println(name + "==" + age);
return 100;
};
MyInterface myInterface = new MyInterface() {
@Override
public int test(String name, int age)
return name.hashCode() + age;
}
};
//第一次简写
MyInterface myInterface2 = (String name, int age) -> {
return name.hashCode() + age;
};
//第二次简写
MyInterface myInterface3 = (name, age) -> {
return name.hashCode() + age;
};
//第三次简写:如果你对接口中的抽象方法的具体实现逻辑,只有一行代码,可以省略return关键字和{}
MyInterface myInterface4 = (name, age) -> name.hashCode() + age;
上述 Lambda 表达式中的参数类型都是由编译器推断得出的。 Lambda 表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。 Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”.
那么其实我们的Lambda表达式就是对函数式接口的一种简写方式,所以只有是函数式接口,我们才能用Lambda表达式.再换句话说,Lambda表达式需要函数式接口的支持,那函数式接口我们可以自己定义,当然JDK1.8也给我们提供了一些现成的函数式接口.
函数式接口的定义是: 只包含一个抽象方法的接口,称为函数式接口。
你可以通过 Lambda 表达式来创建该接口的对象
我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.
//自定义一个函数式接口
@FunctionalInterface //可以检测这个接口是不是个函数式接口
public interface MyInterface {
//函数值接口中只能有一个抽象方法
int show(int a);
}
public static void main(String[] args) {
MyInterface myInterface = new MyInterface() {
@Override
public int show(int a) {
return a + 100;
}
};
MyInterface myInterface2 = a -> a + 200;
//当接口中只有一个抽象方法,才能使用Lambda表达式来简写。
//Lambda表达式之支持函数式接口:接口中只有一个抽象方法
// @FunctionalInterface 这个注解可以检测这个接口是不是个函数式接口。
public static void main(String[] args) {
Integer[] arr = {20, 30, 4, 2};
//Lambda作为参数传递
Arrays.sort(arr, (a, b) -> a - b);
System.out.println(Arrays.toString(arr));
Consumer<Integer> consumer = integer -> System.out.println(integer);
}
对象::实例方法
类::静态方法
类::实例方法
MyClass::new 相当于 () -> new MyClass();
采用构造器引用;MyClass::new;相当于(x)->MyClass(x);
public static void main(String[] args) {
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
PrintStream out = System.out;
out.println(s);
}
};
//简化
Consumer<String> consumer2 = s -> System.out.println(s);
//继续简化
Consumer<String> consumer3 = System.out::println;
//方法引用
//你要看你对接口中这个抽象方法的重写逻辑
//Consumer接口中这个抽象方法 accept(String s) 返回值是void 参数只有一个参数
//我们对这个accept(String s)这个方法的重写逻辑 System.out.println(s);
//对象.println(s) 这个println(s)方法的返回值是void 方法的参数也是一个,正好跟我们重写的accept(String s)
//的返回值类型和参数列表能对应上,那么我就可以使用方法引用,来简写。
BinaryOperator<Double> binaryOperator = new BinaryOperator<Double>() {//进行二元运算的类
@Override
public Double apply(Double aDouble, Double aDouble2) {
double max = Math.max(aDouble, aDouble2);
return max;
}
};
BinaryOperator<Double> binaryOperator2 = (a, b) -> Math.max(a, b);
//方法引用
BinaryOperator<Double> binaryOperator3 = Math::max;
System.out.println("===================================");
}
// BiConsumer
// void accept (T t, U u);
Supplier<Double> supplier = new Supplier<Double>() {
@Override
public Double get() {
Random random = new Random();
double v = random.nextDouble();
return v;
}
};
Supplier<Double> supplier2 = () -> new Random().nextDouble();
Supplier<Double> supplier3 = new Random()::nextDouble;
Predicate<String> stringPredicate = new Predicate<String>() {
@Override
public boolean test(String s) {
boolean b = new String("abc").startsWith(s);
return b;
}
};
Predicate<String> stringPredicate2 = (s) -> new String("abc").startsWith(s);
Predicate<String> stringPredicate3 = new String("abc")::startsWith;
}
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
//传入的两个参数,一个作为了调用者,一个作为了传入者,也可以使用方法引用进行简写。
int i = s1.compareTo(s2);
return i;
}
};
Comparator<String> comparator2 = (s1, s2) -> s1.compareTo(s2);
Comparator<String> comparator3 = String::compareTo;
Supplier<Student> supplier = new Supplier<Student>() {
@Override
public Student get() {
return new Student();
}
};
Supplier<Student> supplier2 = () -> new Student();
//构造引用
Supplier<Student> supplier3 = Student::new;
System.out.println("============================");
BiFunction<String, Integer, Student> biFunction = new BiFunction<String, Integer, Student>() {
@Override
public Student apply(String s, Integer integer) {
return new Student(s, integer);
}
};
BiFunction<String, Integer, Student> biFunction2 = Student::new;