一、简介:
Lambda一个匿名函数看,我们可以把Lambda表达式理解为一段可以传递的代码。可以写出更简洁、更灵活的代码,使代码变的更紧凑。
1.Lambda 表达式的基础语法:
java8中引入了一个新的操作符 “->” 该操作符称为箭头操作符或Lambda操作符操作符将Lambda表达式拆成两部分。
左侧:Lambda 表达式的参数列表
右侧:Lambda 表达式中所需执行的功能,即Lambda体
语法格式一:无参数,无返回值
() - > System.out.println(“迪迦”);
匿名内部类格式
@Test
public void Test1() {
//匿名内部类格式
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("迪迦");
}
};
r1.run();
//Lambda表达式
Runnable r2 = ()-> System.out.println("迪迦");
r2.run();
}
语法格式二:有一个参数,无返回值
(x)->System.out.println(x);
@Test
public void Test2(){
//匿名内部类
Consumer<String> c1= new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}`在这里插入代码片`
};
c1.accept("光的力量");
//Lambda表达式
Consumer<String> c2=(x)-> System.out.println(x);
c2.accept("赛文");
}
语法格式三:若只有一个参数,小括号可以省略不写
x->System.out.println(x)
Consumer<String> c2 = x -> System.out.println(x);
c2.accept("赛文");
语法格式四:有两个以上的参数,有返回值,并且Lambda体中有多条语句
@Test
public void Test3() {
//匿名内部类形式
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println("函数式接口");
return Integer.compare(o1, o2);
}
};
//Lambda表达式
Comparator<Integer> com = (o1, o2) -> {
System.out.println("函数式接口");
return Integer.compare(o1, o2);
};
}
语法格式五:若Lambda体中只有一条语句,return和大括号都可以省略不写
Comparator<Integer> comparator= (o1, o2) -> Integer.compare(o1,o2);
语法格式六:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出数据类型,即“类型推断”
(Integer x,Integer y) -> Integer.compare(x,y);
2.变量作用域
lambda 表达式只能引用标记了 final 的外层局部变量,如果在lambda 内部修改定义在域外的局部变量,会编译错误。
在jdk1.8以后,lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有final 的语义)
@Test
public void Test() {
int num = 0;
Runnable r1 = () -> System.out.println("迪迦"+num);
r1.run();
}
在Test.java中,Lambda表达式中可以引用了局部变量,但是如果修改局部变量的值,将会出现编译错误。
3.Lambda表达式需要“函数式接口”的支持
函数式接口:接口中只有一个抽象方法的接口,称为函数式接口,但是可以有多个非抽象方法的接口。可以用@FunctionalInterface注解修饰
@FunctionalInterface
public interface MyFun {
void test();
}
被此注解修饰的接口只能存在一个方法,否则编译错误。
4.java内置的四大核心函数式接口
消费型接口:Consumer consumer
传入一个泛型T的数据来调用此接口的方法进行操作
@Test
public void TestConsumer() {
happy(10, money -> System.out.println("消费" + money + "元"));
}
public void happy(double money, Consumer<Double> con) {
con.accept(money);
}
输出: 消费10.0元
供给型接口:Supplier supplier
通过调用此接口中的方法,可以返回一个泛型T的数据
@Test
public void TestSupplier() {
List<Integer> numList = getNumList(10, () -> (int) (Math.random() * 100));
System.out.println(numList);
}
//产上参数1指定的数量的整数,并放入集合中
public List<Integer> getNumList(int num, Supplier<Integer> supplier) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
Integer n = supplier.get();
list.add(n);
}
return list;
}
输出:[55, 34, 76, 11, 14, 93, 74, 6, 79, 50]
函数式接口:Function<T, R> fun
将泛型T通过此接口的方法进行操作,并且返回一个泛型R的数据
@Test
public void TestFunction() {
String abcd = strHandler("ABCD", s -> s.toLowerCase());
System.out.println(abcd);
}
public String strHandler(String string, Function<String, String> fun) {
return fun.apply(string);
}
将大写的ABCD字符串转换为小写
输出: abcd
断言型接口:Predicate pre
用来进行一些判断操作
@Test
public void TestPredicate() {
List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
List<String> str = filterStr(list, s -> s.length() > 3);
System.out.println(str);
}
public List<String> filterStr(List<String> list, Predicate<String> pre) {
List<String> strList = new ArrayList<>();
for (String s : list) {
if (pre.test(s)) {
strList.add(s);
}
}
return strList;
}
判断集合中的字符串长度是否大于3,true就添加到List中
输出: [Hello, atguigu, Lambda]