JDK8特性一之Lambda表达式

Java8 新增了非常多的特性,这篇记录Lambda 表达式 。
Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。—来自百度百科

如果是新人先看这篇从Java匿名内部类深入到JDK8的Lombda表达式
首先我们来个例子看看Lambda 表达式给我们带来了什么方便

假设有一个List ,程序员可以使用 for 语句 (“for 循环”)来遍历,在Java SE 8中可以转换为另一种形式:

 
  1. String[] atp = {"Rafael Nadal", "Novak Djokovic",
  2. "Stanislas Wawrinka",
  3. "David Ferrer","Roger Federer",
  4. "Andy Murray","Tomas Berdych",
  5. "Juan Martin Del Potro"};
  6. List<String> players = Arrays.asList(atp);
  7. // 以前的循环方式
  8. for (String player : players) {
  9. System.out.print(player + "; ");
  10. }
  11. // 使用 lambda 表达式以及函数操作(functional operation)
  12. players.forEach((player) -> System.out.print(player + "; "));
  13. // 在 Java 8 中使用双冒号操作符(double colon operator)
  14. players.forEach(System.out::println);

正如您看到的,lambda表达式可以将我们的代码缩减到一行。但是你现在可能不懂上面什么意思,没关系,接下来才正式开始

语法
 
  1. (parameters) -> expression
  2. (parameters) ->{ statements; }

以下是lambda表达式的重要特征:

  1. 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  2. 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  3. 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  4. 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
Lambda 表达式实例
 
  1. // 1. 不需要参数,返回值为 5
  2. () -> 5
  3. // 2. 接收一个参数(数字类型),返回其2倍的值
  4. x -> 2 * x
  5. // 3. 接受2个参数(数字),并返回他们的差值
  6. (x, y) -> x y
  7. // 4. 接收2个int型整数,返回他们的和
  8. (int x, int y) -> x + y
  9. // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
  10. (String s) -> System.out.print(s)

现在再看第一个例子是不是有点懂了,那接下来在看个例子

lambdas 来实现 Runnable接口
 
  1. // 1.1使用匿名内部类
  2. new Thread(new Runnable() {
  3. @Override
  4. public void run() {
  5. System.out.println("Hello world !");
  6. }
  7. }).start();
  8. // 1.2使用 lambda expression
  9. new Thread(() -> System.out.println("Hello world !")).start();
  10. // 2.1使用匿名内部类
  11. Runnable race1 = new Runnable() {
  12. @Override
  13. public void run() {
  14. System.out.println("Hello world !");
  15. }
  16. };
  17. // 2.2使用 lambda expression
  18. Runnable race2 = () -> System.out.println("Hello world !");
  19. // 直接调用 run 方法(没开新线程哦!)
  20. race1.run();
  21. race2.run();

是不是方便了许多呢,Runnable 的 lambda表达式,使用块格式,将五行代码转换成单行语句。 接下来,在下一节中我们将使用lambdas对集合进行排序。

Lambdas排序集合
 
  1. String[] players = {"Rafael Nadal", "Novak Djokovic",
  2. "Stanislas Wawrinka", "David Ferrer",
  3. "Roger Federer", "Andy Murray",
  4. "Tomas Berdych", "Juan Martin Del Potro",
  5. "Richard Gasquet", "John Isner"};
  6. // 1.1 使用匿名内部类根据 name 排序 players
  7. Arrays.sort(players, new Comparator<String>() {
  8. @Override
  9. public int compare(String s1, String s2) {
  10. return (s1.compareTo(s2));
  11. }
  12. });
  13. // 1.2 使用 lambda expression 排序 players
  14. Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
  15. Arrays.sort(players, sortByName);
  16. // 1.3 也可以采用如下形式:
  17. Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));

就是这样,简洁又直观。 在下一篇中我们将探索更多lambdas的能力,并将其与 stream 结合起来使用。

注意:上面使用了::的用法。就是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下,双冒号运算就是Java中的[方法引用],[方法引用]的格式是:

 
  1. 类名::方法名

如:

 
  1. 表达式:
  2. person -> person.getAge();
  3. 使用双冒号:
  4. Person::getAge
  5. 表达式:
  6. new HashMap<>()
  7. 使用双冒号:
  8. HsahMap :: new