Lambda表达式
创建多线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<10 ;i++) {
System.out.println("简化runnable接口: "+Thread.currentThread().getName());
}
}
}).start();
new Thread(()-> {
System.out.println("简化runnable接口: "+Thread.currentThread().getName());
}).start();
Lambda表达式的标准格式
由三各分组成
a:一些参数
b:一个箭头
c:一个方法体
格式
(参数列表)->{一些重写方法的代码}
解释说明格式
():接口中抽象方法的参数列表,没有参数,就空着:有参数就写出参数,多个参数使用逗号分隔
->:传递的意思,把参数传读给方法体{}
{}:重写接口的抽象方法的方法体
Person[] arr = {
new Person("zhangsan",23),
new Person("lisi",12),
new Person("oyu", 55)
};
// Arrays.sort(arr,new Comparator<Person>() {
//
// @Override
// public int compare(Person o1, Person o2) {
// return o1.getAge() - o2.getAge();
// }
// });
Arrays.sort(arr,(Person o1,Person o2)->{
return o1.getAge() - o2.getAge();
});
for (Person p : arr) {
System.out.println(p);
}
Lambda表达式:是可推导,可以省略
凡是根据上下文推导出来的内容,都可以省略书写
可以省略的内容
1.(参数列表):括号中参数列表的数据类型,可以省略
2.(参数列表):括号中的参数列表如果只有一个,那么类型和()都可以省略
3,{一些代码}:如果{}中的代码只有一行吗,无论是否有返回值,都可以省略({},return,分号)
注意:要省略{}, return,分号必须一起省略
特别注意:
1.使用Lambda必须具有接口,且接口有且仅有一个抽象方法
无论是JDK内置的Runnable,Comparator接口还是自定义的接口,只有当接口的抽象方法存在且唯一时,才可以使用Lambda
2.使用Lambda必须具有上下文推断
也就是方法的参数或局部类型必须为Lambda的接口类型,才能使用Lambda作为Lambda作为该接口的实例
函数式接口
函数式接口:有且仅有一个抽象方法的接口,称为"函数式接口" 可以包含其他的方法(默认,静态,私有)
@FunctionalInterface注解
作用:可以检测接口是否是一个函数式接口
是:编译成功
否:编译失败(接口中没有抽象方法或抽象方法的个数多余1个)
使用:一般可以作为方法的参数和返回值类型
特点:延迟加载
使用前提:必须存在函数式接口
使用Lambda表达式作为参数传递
使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中
只有满足条件,日志的等级是1级
才会调用接口MessageBuilder中的方法builderMessage
才会进行字符串的拼接
如果条件不满足
那么MessageBuilder接口中的方法builderMessage也不会执行
所以拼接字符串的代码也不会执行
public static void main(String[] args) {
String msg1 = "hello";
String msg2 = "world";
String msg3 = "java";
showLog(2, ()->msg1+msg2+msg3);
}
public static void showLog(int level,MessageBuilder mb) {
if(level == 1) {
System.out.println(mb.builderMessage());
}
}
}
interface MessageBuilder {
public abstract String builderMessage();
}
使用Lambda表达式作为返回值类型传递
使用Lambda表达式作为返回值类型传递,我们可以返回这个接口的匿名内部类,也使用lambd表达式
public static Comparator<String> getComparator(){
return ( o1, o2)->o1.length() - o2.length();
}
public static void main(String[] args) {
String[] arr = {"123","22","4567"};
System.out.println(Arrays.toString(arr));
Arrays.sort(arr, getComparator());
System.out.println(Arrays.toString(arr));
}
常用的函数式接口:
java.util.function.Supplier<T>生产型接口:
1.仅包含一个无参的方法:T get(). 用来获取一个泛型参数指定类型的对象数据
2.Supplier<T> 接口被称为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法
就会生产什么类型的数据
3.定一个方法,参数传递supplier<T>接口,泛型执行String ,get就会返回一个String
4.调用方法,可以传递lambda表达式
public static String getString(Supplier<String> sup) {
return sup.get();
}
public static void main(String[] args) {
String s = getString(()->{
return "胡歌";
});
System.out.println(s);
}
java.util.function.Consumer<T>消费型接口:
1.它不是生产一个数据,而是消费一个数据,其类型由泛型决定.
2.Consumer接口中包含抽象方法 void accept(T t),意为消费一个指定泛型的数据
3.泛型执行什么类型,就可以使用accept方法消费什么类型的数据,至于怎么消费,需要自定义(输出,计算...)
public static void method(String name ,Consumer<String> con) {
con.accept(name);
}
public static void main(String[] args) {
method("赵丽颖",(String name)->{
System.out.println(name);
String reName = new StringBuilder(name).reverse().toString();
System.out.println(reName);
});
默认方法andThen:
作用:需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费
例如:con1.andThen(con2).accept(s); 谁写前边谁先消费
java.util.function.Predicator<T>断言型接口:
作用:对某种数据类型的数据进行判断,结果返回一个boolean值
抽象方法:
boolean test(T t):用来对指定数据类型进行判断的方法
默认方法:
1.and()方法,表示并且关系,用于连接两个判断条件 等价于&&
2.or()方法,表示或的关系, 等价于||
3.negate()方法,表示非的关系 等价于!
java.util.function.Function<T,R>函数型接口:
1.用来根据一个类型的数据得到另一个类型的数据
2.前者为前置条件,后者为后置条件
抽象方法:
R apply(T t):根据类型T的参数获取类型R的结果
例如:将String类型转换为Integer类型
默认方法: andThen 用来进行组合,表示连接