Lambda基本语法
Java8中引入了新的操作符” - >“符号,称为箭头操作符,它将表达式拆分为两部分
左侧:lambda表达式参数列表
右侧:lambda表达式所执行的功能,执行体
适用于函数式接口(下面介绍)
语法格式一:无参数,无返回值
() -> System.out.printIn("hello");
比如:Runnable接口中的run方法
@Test
public void test() {
new Thread(() -> {for (int i = 0; i < 20; i++)
{
System.out.println("我在跑"+i);
}
}).start();
}
语法格式二:有一个参数,无返回值
(x)-> System.out.printIn(x);
@Test
public void test() {
Consumer<String > consumer = (x) -> System.out.println(x);
consumer.accept("我的大哥");
}
语法格式三:如果只有一个参数,小括号可以省略不写
x -> System.out.printIn(x);
语法格式四:有两个以上的参数,并且lambda体中有多条语句,有返回值
(x,y)-> { 语句 }
@Test
public void test() {
Comparator<Integer> comparator = (x,y)->{
return Integer.compare(x,y);
};
System.out.println(comparator.compare(30, 20));
}
语法格式五:Lambda表达式中的参数列表的数据类型可以省略不写
因为JVM编译器可以通过上下文推断出数据类型,即”类型推断“
比如 String[] strs = {"aaa","bbb","ccc"} ,
ArrayList<String> objects = new ArrayList<>();
拆开写就不行String strs; strs = {"a","b"};
但是如果一个参数写上类型其余的参数也要写。
练习
一、对于学生信息进行排序,按年龄排序,如果年龄相同按学号排序
/**
* @author wy
*/
@Data
public class Student {
private String name;
private int age;
private int sno;
public Student(String name, Integer age, Integer sno) {
this.name = name;
this.age = age;
this.sno = sno;
}
}
@Test
public void test1(){
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("张三1",40,1));
students.add(new Student("张三2",20,2));
students.add(new Student("张三3",30,3));
students.add(new Student("张三4",40,4));
Collections.sort(students,(e1,e2)->{
if (e1.getAge()==e2.getAge()){
return Integer.compare(e1.getSno(),e2.getSno());
}else {
return Integer.compare(e1.getAge(),e2.getAge());
}
});
students.stream().forEach(System.out::println);
}
二、完成对字符串的特定操作
如将字符串转化为大写
/**
* @author wy
*/
@FunctionalInterface
public interface MyFun<T> {
public T getValue(T t);
}
@Test
public void test2(){
System.out.println(strHandler("hello", String::toUpperCase));
}
public String strHandler(String str,MyFun<String> myFun){
return myFun.getValue(str);
}
函数式接口
什么时函数式接口
接口中只有一个抽象方法时,这个接口就是函数式接口。
函数时接口可以使用注解 @FunctionalInterface修饰,可以检查接口是不是函数式接口
内置函数式接口
像上面的操作,我们需要创建一个函数式接口去支持
java为我们提供了一些函数式接口供我们使用
Consumer<T> : 消费型接口
方法:void accept(T t);
@Test
public void test4(){
happy(1000.00,(x)-> System.out.println("我洗了"+x+"元的澡,就是消费,我开心"));
}
public void happy(Double money,Consumer<Double> consumer){
consumer.accept(money);
}
Supplier<T>:供给型接口
方法:T get();
需求:产生指定个数整数,放入集合中
@Test
public void test5(){
getNumList(5,()->(int)(Math.random()*100)).forEach(System.out::println);
}
public List<Integer> getNumList(int num, Supplier<Integer> supplier){
ArrayList<Integer> integers = new ArrayList<>();
for (int i=0;i<num;i++) {
Integer integer = supplier.get();
integers.add(integer);
}
return integers;
}
Function<T , R> :函数型接口
方法:R apply(T t);
需求:处理字符串 转化为大写
@Test
public void test9(){
System.out.println(strHandler2("abc", (x)->x.toUpperCase()));
}
public String strHandler2(String str, Function<String,String> function){
return function.apply(str);
}
Predicate<T >;断言型接口
方法:boolean test(T t);
需求:将满足条件字符串添加到集合中去
public void test8(){
List<String> list = Arrays.asList("Hello","nihao","lambda","ok");
System.out.println(filterStr(list, (s) -> s.length() > 3));
}
public List<String> filterStr(List<String> strings, Predicate<String> predicate){
ArrayList<String> strings1 = new ArrayList<>();
for (String s: strings) {
if (predicate.test(s)){
strings1.add(s);
}
}
return strings1;
}
方法引用
方法引用:
若lambda表达式体中的内容有方法已经实现了,我们可以使用“方法引用”
注意:
1、lambda方法体中方法的参数列表和返回值,要与函数式接口中的抽象方法的参数列表和返回值相同
2、若lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method
语法格式:
对象::实例方法名
@Test
public void test11() {
Consumer<String> consumer = (s -> System.out.println(s));
//lambda体中的方法已经实现了改功能
//接口中的参数列表和返回值要与方法中的参数列表和返回值相同
PrintStream out = System.out;
Consumer<String> consumer1 = out::println;
Consumer<String > consumer2 = System.out::println;
consumer2.accept("abc");
}
@Test
public void test12(){
//供给性接口返回学生的名字
Student student = new Student();
Supplier<String> stringSupplier = ()-> student.getName();
System.out.println(stringSupplier.get());
Supplier<String> stringSupplier1 = student::getName;
}
类::静态方法名
@Test
public void test13(){
Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
Comparator<Integer> comparator1= Integer::compare;
}
类::实例方法名
@Test
public void test14(){
//比较两个字符串是不是一样
BiPredicate<String,String> bp = (x,y)->x.equals(y);
BiPredicate<String,String> bp1 = String::equals;
}
构造器引用
格式:
构造器::方法
第一个Student::new使用的是无参构造器
第二个Student::new使用的是有一个参数的构造器
@Test
public void test15(){
Supplier<Student> studentSupplier = ()->new Student();
Student student = studentSupplier.get();
//构造器引用
Supplier<Student> studentSupplier1 = Student::new;
Function<String,Student> function = Student::new;
Student student1 = function.apply("www");
System.out.println(student1.getName());
}