摘要:看到大佬的代码有 “->” 以及 “::” 这种符号,后面查询后得知这是λ表达式,本质上就是一种语法糖
1. lambda
1.1基本介绍
Lambda 表达式是 JDK1.8 开始之后的新技术,是一种代码的新语法,一种特殊写法
作用:为了简化匿名内部类的代码写法
Lambda 表达式的格式:
(匿名内部类被重写方法的形参列表) -> {
//被重写方法的方法体代码
}
Lambda 表达式并不能简化所有匿名内部类的写法,只能简化函数式接口的匿名内部类
简化条件:首先必须是接口,接口中只能有一个抽象方法
@FunctionalInterface 函数式接口注解:一旦某个接口加上了这个注解,这个接口只能有且仅有一个抽象方法
1.2简化方法
Lambda 表达式的省略写法(进一步在 Lambda 表达式的基础上继续简化)
- 如果 Lambda 表达式的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号;如果这行代码是 return 语句,必须省略 return 不写
- 参数类型可以省略不写
- 如果只有一个参数,参数类型可以省略,同时
()也可以省略
List<String> names = new ArrayList<>();
names.add("a");
names.add("b");
names.add("c");
names.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
names.forEach((String s) -> {
System.out.println(s);
});
names.forEach((s) -> {
System.out.println(s);
});
names.forEach(s -> {
System.out.println(s);
});
names.forEach(s -> System.out.println(s) );
1.3常用简化
Comparator
public class CollectionsDemo {
public static void main(String[] args) {
List<Student> lists = new ArrayList<>();//...s1 s2 s3
Collections.addAll(lists , s1 , s2 , s3);
Collections.sort(lists, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return s1.getAge() - s2.getAge();
}
});
// 简化写法
Collections.sort(lists ,(Student t1, Student t2) -> {
return t1.getAge() - t2.getAge();
});
// 参数类型可以省略,最简单的
Collections.sort(lists ,(t1,t2) -> t1.getAge()-t2.getAge());
}
}
2. 方法引用
2.1基本介绍
方法引用:方法引用是为了进一步简化 Lambda 表达式的写法
方法引用的格式:类型或者对象::引用的方法
关键语法是:::
lists.forEach( s -> System.out.println(s));
// 方法引用!
lists.forEach(System.out::println);
2.2静态方法
引用格式:类名::静态方法
简化步骤:定义一个静态方法,把需要简化的代码放到一个静态方法中去
静态方法引用的注意事项:被引用的方法的参数列表要和函数式接口中的抽象方法的参数列表一致,才能引用简化
//定义集合加入几个Student元素
// 使用静态方法进行简化!
Collections.sort(lists, (o1, o2) -> Student.compareByAge(o1 , o2));
// 如果前后参数是一样的,而且方法是静态方法,既可以使用静态方法引用
Collections.sort(lists, Student::compareByAge);
public class Student {
private String name ;
private int age ;
public static int compareByAge(Student o1 , Student o2){
return o1.getAge() - o2.getAge();
}
}
2.3实例方法
引用格式:对象::实例方法
简化步骤:定义一个实例方法,把需要的代码放到实例方法中去
实例方法引用的注意事项:被引用的方法的参数列表要和函数式接口中的抽象方法的参数列表一致。
public class MethodDemo {
public static void main(String[] args) {
List<String> lists = new ArrayList<>();
lists.add("java1");
lists.add("java2");
lists.add("java3");
// 对象是 System.out = new PrintStream();
// 实例方法:println()
// 前后参数正好都是一个
lists.forEach(s -> System.out.println(s));
lists.forEach(System.out::println);
}
}
2.4特定类型
特定类型:String,任何类型
引用格式:特定类型::方法
注意事项:如果第一个参数列表中的形参中的第一个参数作为了后面的方法的调用者,并且其余参数作为后面方法的形参,那么就可以用特定类型方法引用了
public class MethodDemo{
public static void main(String[] args) {
String[] strs = new String[]{"James", "AA", "John",
"Patricia","Dlei" , "Robert","Boom", "Cao" ,"black" ,
"Michael", "Linda","cao","after","sa"};
// public static <T> void sort(T[] a, Comparator<? super T> c)
// 需求:按照元素的首字符(忽略大小写)升序排序!!!
Arrays.sort(strs, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);//按照元素的首字符(忽略大小写)
}
});
Arrays.sort(strs, ( s1, s2 ) -> s1.compareToIgnoreCase(s2));
// 特定类型的方法引用:
Arrays.sort(strs, String::compareToIgnoreCase);
System.out.println(Arrays.toString(strs));
}
}
2.5构造器
格式:类名::new
注意事项:前后参数一致的情况下,又在创建对象,就可以使用构造器引用
public class ConstructorDemo {
public static void main(String[] args) {
List<String> lists = new ArrayList<>();
lists.add("java1");
lists.add("java2");
lists.add("java3");
// 集合默认只能转成Object类型的数组。
Object[] objs = lists.toArray();
// 我们想指定转换成字符串类型的数组!最新的写法可以结合构造器引用实现
String[] strs = lists.toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
String[] strs1 = lists.toArray(s -> new String[s]);
String[] strs2 = lists.toArray(String[]::new);
System.out.println("String类型的数组:"+ Arrays.toString(strs2));
}
}