剖析Java8的lamda表达式01

《笔者带你剖析Java8的lamda表达式01》

 

其实Java8从诞生到至今,3年多的时间里笔者一直没有在任何项目中正式使用到Java8和lamda。时光飞逝,当我们还停留在Java6和Java7的语法层面时,9的正式版也即将来到我们身边,真的是感觉到惭愧,所以笔者抽空整理了一下lamda的一些表达式语法,同时也准备在项目中柔和进它。

 

首先我们来看看,使用Lamda有什么好处,没好处的事情相信谁也不愿意牺牲稳定性去尝鲜。lamda对语法层面的改变2个字总结就是:简洁。因此可以把lamda表达式理解为简洁的表示可传递的匿名函数的一种方式。

 

lamda的构成,如下所示:

图1 lamda表达式的构成结构

 

lamda表达式的构成结构由3部分构成,首先是lamda的参数列表,其次是箭头符号,最后是lamda的函数主体。那么看到现在,我们先来点实在的东西,如何使用Lamda表达式,思考一下,在Java8之前,我们使用线程的时候,大部分情况下,都是通过匿名类的的方式进行实现,那么看看如何使用lamda表达式进行改造:

/* 匿名类的用法 */
new Thread(new Runnable() {
 @Override
 public void run() {
  System.out.println(Thread.currentThread().getId());
 }
}).start();
/* lamda用法 */
new Thread(() -> System.out.println(Thread.currentThread().getId())).start();

你的第一感觉是什么?反正我的感觉清爽和简洁,因为再也不必要那浪费时间去编写样板代码。你可能会产生疑问,如果我的函数主体由多行构成的时候应该怎么办呢?lamda表达式的基本语法如下:

Runnable t1 = () -> System.out.println(Thread.currentThread().getId());
/* 如果函数主体由多行构成,则使用花括号{} */
Runnable t2 = () -> {
 for (int i = 0; i < 10; i++) {
  // ...
 }
};

学了新技能,就要考虑在哪里能够欢快的使用,lamda可以使用在函数式接口上。函数式接口眨一听,略带抽象,简单来说,就是一个被定义了@FunctionalInterface注解且仅包含一个抽象方法的接口,这就是所谓的函数式接口,那么被@FunctionalInterface注解标记的接口如果包含了2个抽象方法,编译器会告知“Invalid '@FunctionalInterface' annotation; CompareObj is not a functional interface”。

当然函数式接口中的抽象方法也被称之为函数描述符,因为接口中抽象方法的方法签名基本上就是lamda表达式的签名。你试想一下,如果一个函数式接口中包含N个抽象方法,我们在使用lamda表达式时,编译器如何区lamda表达式的签名应该对应哪一个方法签名呢?

@FunctionalInterface
public interface CompareObj {
 public boolean compare();
 public boolean compare2();
 /* CompareObj comObj=()->true;编译器如何清楚所对应的具体方法? */
}

 再回到函数式接口这个话题,刚才笔者也说了,被@FunctionalInterface标记的接口我们可以称之为函数式接口,但这个注解并不是必须的(Java8中Runnable以及Callable等接口已经标注了该注解),但好的编码习惯只会对实际的开发过程中带来意想不到的帮助。那么接下来我们就来定义一个函数式接口,并在它上面使用Lamda表达式:

@FunctionalInterface
public interface Compare {
 public boolean compare(String str1, String str2);
 /* Java8允许接口中定义实现 */
 public static void main(String[] args) {
  testCompare((String str1, String str2) -> str1.equals(str2), "a", "b");
 }
 public static boolean testCompare(Compare c, String str1, String str2) {
  return c.compare(str1, str2);
 }
}

 

除了可以自定义函数式接口,Java8 API也为开发人员提供了一些较为常用和常见的函数式接口:Predicate、consumer、Funtion,这些接口都被包含在java.util.funtion包下。

 

当然笔者并不会全部对这些接口进行介绍,感兴趣的同学可以自行研究其用法,笔者仅挑 Predicate<T>接口进行演示。在该接口中包含一个返回值为boolean类型的test()的抽象方法,我们可以使用该函数式接口来验证一个涉及类型为T的布尔表达式,如下所示:

Predicate<String> p = (String str) -> StringUtils.isEmpty(str);
System.out.println(p.test("lamda"));

 

 

《笔者带你剖析Java8的lamda表达式01》

 

其实Java8从诞生到至今,3年多的时间里笔者一直没有在任何项目中正式使用到Java8和lamda。时光飞逝,当我们还停留在Java6和Java7的语法层面时,9的正式版也即将来到我们身边,真的是感觉到惭愧,所以笔者抽空整理了一下lamda的一些表达式语法,同时也准备在项目中柔和进它。

 

首先我们来看看,使用Lamda有什么好处,没好处的事情相信谁也不愿意牺牲稳定性去尝鲜。lamda对语法层面的改变2个字总结就是:简洁。因此可以把lamda表达式理解为简洁的表示可传递的匿名函数的一种方式。

 

lamda的构成,如下所示:

图1 lamda表达式的构成结构

 

lamda表达式的构成结构由3部分构成,首先是lamda的参数列表,其次是箭头符号,最后是lamda的函数主体。那么看到现在,我们先来点实在的东西,如何使用Lamda表达式,思考一下,在Java8之前,我们使用线程的时候,大部分情况下,都是通过匿名类的的方式进行实现,那么看看如何使用lamda表达式进行改造:

/* 匿名类的用法 */
new Thread(new Runnable() {
 @Override
 public void run() {
  System.out.println(Thread.currentThread().getId());
 }
}).start();
/* lamda用法 */
new Thread(() -> System.out.println(Thread.currentThread().getId())).start();

你的第一感觉是什么?反正我的感觉清爽和简洁,因为再也不必要那浪费时间去编写样板代码。你可能会产生疑问,如果我的函数主体由多行构成的时候应该怎么办呢?lamda表达式的基本语法如下:

Runnable t1 = () -> System.out.println(Thread.currentThread().getId());
/* 如果函数主体由多行构成,则使用花括号{} */
Runnable t2 = () -> {
 for (int i = 0; i < 10; i++) {
  // ...
 }
};

学了新技能,就要考虑在哪里能够欢快的使用,lamda可以使用在函数式接口上。函数式接口眨一听,略带抽象,简单来说,就是一个被定义了@FunctionalInterface注解且仅包含一个抽象方法的接口,这就是所谓的函数式接口,那么被@FunctionalInterface注解标记的接口如果包含了2个抽象方法,编译器会告知“Invalid '@FunctionalInterface' annotation; CompareObj is not a functional interface”。

当然函数式接口中的抽象方法也被称之为函数描述符,因为接口中抽象方法的方法签名基本上就是lamda表达式的签名。你试想一下,如果一个函数式接口中包含N个抽象方法,我们在使用lamda表达式时,编译器如何区lamda表达式的签名应该对应哪一个方法签名呢?

@FunctionalInterface
public interface CompareObj {
 public boolean compare();
 public boolean compare2();
 /* CompareObj comObj=()->true;编译器如何清楚所对应的具体方法? */
}

 再回到函数式接口这个话题,刚才笔者也说了,被@FunctionalInterface标记的接口我们可以称之为函数式接口,但这个注解并不是必须的(Java8中Runnable以及Callable等接口已经标注了该注解),但好的编码习惯只会对实际的开发过程中带来意想不到的帮助。那么接下来我们就来定义一个函数式接口,并在它上面使用Lamda表达式:

@FunctionalInterface
public interface Compare {
 public boolean compare(String str1, String str2);
 /* Java8允许接口中定义实现 */
 public static void main(String[] args) {
  testCompare((String str1, String str2) -> str1.equals(str2), "a", "b");
 }
 public static boolean testCompare(Compare c, String str1, String str2) {
  return c.compare(str1, str2);
 }
}

猜你喜欢

转载自gao-xianglong.iteye.com/blog/2399456
今日推荐