在正式学习Lambda之前,我们先来了解一下什么是函数式编程
我们先看看什么是函数。函数是一种最基本的任务,一个大型程序就是一个顶层函数调用若干底层函数,这些被调用的函数又可以调用其他函数,即大任务被一层层拆解并执行。所以函数就是面向过程的程序设计的基本单元。
Java不支持单独定义函数,但可以把静态方法视为独立的函数,把实例方法视为自带this参数的函数。而函数式编程(请注意多了一个“式”字)——Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。
我们首先要搞明白计算机(Computer)和计算(Compute)的概念。在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Lisp语言。
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
函数式编程最早是数学家阿隆佐·邱奇研究的一套函数变换逻辑,又称Lambda Calculus(λ-Calculus),所以也经常把函数式编程称为Lambda计算。
Java平台从Java 8开始,支持函数式编程。
Lambda初体验先从一个例子开始,让我们来看一下Lambda可以用在什么地方。
例一:创建线程常见创建线程的方法(JDK1.8以前)
//JDK1.7通过匿名内部类的方式创建线程 Thread thread = new Thread(new Runnable() { @Override public void run() { //实现run方法 System.out.println("Thread Run..."); } }); thread.start();通过匿名内部类的方式创建线程,省去了取名字的烦恼,但是还能不能再简化一些呢?
JDK1.8 Lambda表达式写法
Thread thread = new Thread(() -> System.out.println("Thread Run")); //一行搞定 thread.start();我们可以看到Lambda一行代码就完成了线程的创建,简直不要太方便。(至于Lambda表达式的语法,我们下面章节再详细介绍)
如果你的逻辑不止一行代码,那么你还可以这么写
Thread thread = new Thread(() -> { System.out.println("Thread Run"); System.out.println("Hello"); }); thread.start();用{}将代码块包裹起来
例二:自定义比较器我们先来看一下JDK1.7是如何实现自定义比较器的
List<String> list = Arrays.asList("Hi", "Life", "Hello~", "World"); Collections.sort(list, new Comparator<String>(){// 接口名 @Override public int compare(String s1, String s2){// 方法名 if(s1 == null) return -1; if(s2 == null) return 1; return s1.length()-s2.length(); } }); //输出排序好的List for (String s : list) { System.out.println(s); }这里的sort方法传入了两个参数,一个是待排序的list,一个是比较器(排序规则),这里也是通过匿名内部类的方式实现的比较器。
下面我们来看一下Lambda表达式如何实现比较器?
List<String> list = Arrays.asList("Hi", "Life", "Hello~", "World"); Collections.sort(list, (s1, s2) ->{// 省略了参数的类型,编译器会根据上下文信息自动推断出类型 if(s1 == null) return -1; if(s2 == null) return 1; return s1.length()-s2.length(); }); //输出排序好的List for (String s : list) { System.out.println(s); }我们可以看到,Lambda表达式和匿名内部类的作用相同,但是省略了很多代码,可以大大加快开发速度
Lambda表达式语法Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。上一章节我们已经见识到了Lambda表达式的优点,那么Lambda表达式到底该怎么写呢?
语法lambda 表达式的语法格式如下:
(parameters) -> expression //一行代码 或 (parameters) ->{ statements; } //多行代码lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。