lambda表示数学符号“λ”,计算机领域中λ表明“λ演算”,表达了计算机中最基本的概念:“调用”和“置换”。html
全局model代码:Employee.javajava
package www.muzi.com.model; /** * Date:2017/3/3 12:44 */ public class Employee { private String name; private int age; public Employee() { } public Employee(String name, int age) { this.name = name; this.age = age; } public Employee(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Java8中引入了一个新的操做符"->",该操做符称做箭头操做符或者Lambda操做符,箭头操做符将Lambda表达式拆分为两部分:编程
左侧:Lambda 表达式参数列表
右侧:Lambda 表达式中须要执行的功能,及Lambda体api
public void repeatMessage(String content, int count) { Runnable r = () -> { for (int i = 0; i < count; i++) { System.out.println(i + "-" + content); count++;//错误,不能更改已捕获变量的值 } }; r.run(); } @Test public void test8() { repeatMessage("测试", 10); }
@Test public void test9(){ //嵌套台代码块 String ss = ""; { String ss="dd"; } //Lambda Comparator<String> com = (ss, yy) -> Integer.compare(ss.length(), yy.length()); System.out.println(ss); }
语法格式一:无参数,无返回值 () -> System.out.println("Hello Lambda");数组
@Test public void test1(){ int num = 0; //jdk1.7以前,必须是final的 Runnable r = new Runnable() { @Override public void run() { System.out.println("Hello World!" + num); } }; r.run(); System.out.println("------------------"); Runnable r1 = () -> System.out.println("Hello Lambda!" + num); r1.run(); }
语法格式二:有一个参数,无返回值 (x) -> System.out.println(x);闭包
语法格式三:当只有一个参数时,小括号能够省略不写 x -> System.out.println(x);oracle
@Test public void test2(){ Consumer<String> con = (x) -> System.out.println(x); Consumer<String> con1 = x -> System.out.println(x); con.accept("测试Lambda表达式!"); }
语法格式四:当有两个或以上参数时,有返回值,而且Lambda中有多条语句
(x, y) -> {
System.out.println("函数式接口");
return Integer.compare(x, y);
};app
@Test public void test3(){ Comparator<Integer> com = (x, y) -> { System.out.println("函数式接口"); return Integer.compare(x, y); }; System.out.println(com.compare(2, 3)); }
语法格式五:当有两个或以上参数时,有返回值,Lambda中有一条语句,大括号和return能够省略不写dom
(x, y) -> Integer.compare(x, y);ide
@Test public void test4(){ Comparator<Integer> com = (x, y) -> Integer.compare(x, y); System.out.println(com.compare(2, 3)); }
语法格式六:Lambda参数列表的数据类型能够省略不写,由于JVM编译器能够经过上下文推断出,数据类型,即“类型推断”
(Integer x, Integer y) -> Integer.compare(x, y);
@Test public void test5(){ Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y); System.out.println(com.compare(2, 3)); //类型推断举例 List<String> list = new ArrayList<>();//jdk1.7中new ArrayList<String>()必须带类型,1.8版本不须要带类型 }
函数式接口:接口中只有一个抽象方法的接口,成为函数式接口。
可使用注解@FunctionalInterface修饰,能够检查是不是函数式接口。
函数式接口源代码:
package www.muzi.com; /** * Date:2017/3/6 18:02 */ @FunctionalInterface public interface MyFun<T> { public Integer getValue(Integer num); }
//需求:对一个数进行运算 @Test public void test6(){ Integer num = operation(100, x -> x * x); System.out.println("num = " + num); Integer num1 = operation(200, y -> y + 200); System.out.println("num1 = " + num1); } public Integer operation(Integer num, MyFun<Integer> mf){ return mf.getValue(num); }
由于目前在写Lambda表达式时,老是须要去写一个函数式接口。这样其实也挺繁琐,其实Java8已经替咱们内置了许多函数式接口,接下来介绍Java8内置四大函数式接口。
在Java8中添加了许多内置的函数式接口:
这里就展现如下四中函数式接口,其余函数式接口看java8文档:
http://docs.oracle.com/javase/8/docs/api/index.html
//Consumer<T> : 消费型接口 @Test public void test1(){ happy(10000, m -> System.out.println("订餐消费" + m + "元")); } public void happy(double money, Consumer<Double> con){ con.accept(money); };
//Supplier<T> : 供给型接口 @Test public void test2(){ List<Integer> numList = getNumberList(10, () -> (int)(Math.random() * 100)); for (Integer n : numList) { System.out.println(n); } } //需求:产生指定个数的整数,并放到集合中 public List<Integer> getNumberList(int num, Supplier<Integer> sup){ List<Integer> list = new ArrayList<>(); for (int i = 0; i < num; i++) { Integer n = sup.get(); list.add(n); } return list; };
//Function<T, R> : 函数型接口 @Test public void test3(){ String str = strHandler("测试函数式接口 ", x -> x.trim()); System.out.println(str + "--"); } //需求:处理字符串 public String strHandler(String str, Function<String, String> fun){ return fun.apply(str); }
方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可使用方法引用(能够将方法引用理解为 Lambda 表达式的另一种表现形式)。
::操做符将方法名和对象或类的名字分隔开来,主要介绍常使用的三种方法引用方式。
//对象的引用 :: 实例方法名 @Test public void test1(){ Consumer<Integer> con = (x) -> System.out.println(x); //使用方法引用实现 PrintStream ps = System.out; Consumer<Integer> con1 = ps::println; Consumer<Integer> con2 = System.out::println; con2.accept(1234); } @Test public void test2(){ Employee employee = new Employee("木子",23); Supplier<String> sup = employee:: getName; String name = sup.get(); System.out.println(name); }
//类名 :: 静态方法名 @Test public void test3(){ Comparator<Integer> com = (x, y) -> Integer.compare(x, y); //方法引用 //方法引用所引用的方法的参数列表与返回值类型,须要与函数式接口中抽象方法的参数列表和返回值类型保持一致! Comparator<Integer> com1 = Integer:: compare; int result = com1.compare(3, 5); System.out.println(result); }
//类名 :: 实例方法名 @Test public void test4(){ BiPredicate<String, String> bp = (x, y) -> x.equals(y); //若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName BiPredicate<String, String> bp1 = String:: equals; boolean result = bp1.test("as", "as"); System.out.println(result); }
注意:
①方法引用所引用的方法的参数列表与返回值类型,须要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
格式: ClassName :: new
//构造器引用 @Test public void test5(){ Supplier<Employee> sup = () -> new Employee(); //构造器引用,自动匹配对应的构造器 Supplier<Employee> sup1 = Employee::new;//由于没有传参数,这里的new引用的是无参构造器 Employee employee = sup1.get(); System.out.println(employee); //Employee{name='null', age=0} } @Test public void test6(){ Function<String, Employee> fun = (x) -> new Employee(x); Function<String, Employee> fun1 = Employee::new;//这里引用的是一个参数的构造器 System.out.println(fun1.apply("haha"));//Employee{name='haha', age=0} }
构造器引用 : 构造器的参数列表,须要与函数式接口中参数列表保持一致!
格式: Type :: new
//数组引用 @Test public void test7(){ Function<Integer, String[]> fun = (x) -> new String[x]; String[] strs = fun.apply(10); System.out.println(strs.length); //10 Function<Integer, String[]> fun1 = String[]::new; String[] strs1 = fun.apply(15); System.out.println(strs1.length); //15 }