一.什么是lambda?

  在Java中,我们可以将一个值赋值给一个Java变量。

int aValue = 129;
String aString = "hello world";
Boolean aBoolean = true;  

  但是,我们可以将一块代码或者一个方法赋值给一个Java变量么(类似于javascript那样给方法取名字)?

aMethodOfCode = public void doSomething(String s){System.out.println(s);}

  以上操作,在Java8之前是不能做到的,在8之后,使用lambda表达式的特性,就可以做的到了。但是上面的代码还是太过于冗余,不够“优雅”,所以java做了一些优化。

  • 1.public 是多余的: aMethodOfCode = void doSomething(String s){System.out.println(s);}
  • 2.函数名称doSomething是多余的,因为函数名称已经赋值给了aMethodOfCode,并不需要原本的函数名称了:aMethodOfCode = void (String s){System.out.println(s);}
  • 3.返回值是多余的,因为我们在代码里会写是否有返回值,编译器可以自己判断是否有返回值以及返回值的类型:aMethodOfCode = (String s) {System.out.println(s);}
  • 4.参数是多余的,你给定什么参数,编译器会自己判断: aMethodOfCode= (s){System.out.println(s);}
  • 5.大括号是如果在只有一行代码的情况下,是多余的: aMthodOfCode = (s)System.out.println(s)
  • 6.感觉直接这样写有点太丑,需要其他的东西,那就在参数和方法体之间加入一个->,表示这个参数传入到这个方法体里面执行:aMethodOfCode = (s) -> System.out.println(s);

Lambda表达式有什么用?

  经过以上的操作,我们就把一个方法传递给了一个变量,但是Java是一门强类型的语言,那么这个变量应该是一个什么类型的呢? 即如何声明这个变量的类型?在Java8之中,所有的Lambda的类型都是一个接口!而我们上面写的lambda表达式本身,是一个接口的具体实现,也就是说,我们的代码,实际上是一个具体的接口实现,只不过我们没有和之前一样定义一个class显示的实现,在java8之前,这样的操作我们可以通过实现接口,或者匿名内部类两种方式,例如一个排序操作:


/**
* 声明一个学生容器,现在要按照学生的id顺序,
*/
public class LambdaTest {

public static void main(String [] args){
List<Student> list = new ArrayList<>();

list.add(new Student(1,"张三"));
list.add(new Student(2,"李四"));

//现在要对list里面的内容进行排序,按照id的大小顺序排序,使用Collections.sort方法

//1. 使用自定义的compare类(见下面),实现compare方法
Collections.sort(list,new MyCompare());

//2. 使用匿名内部类
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
if (o1.getId()==o2.getId()) return 0;
return o1.getId()>o2.getId()?1:-1;
}
});

//3.使用lambda表达式
Collections.sort(list,(s1,s2)-> Integer.compare(s1.getId(),s2.getId()));

}

}

//第一中方法自己实现的compare方法
class MyCompare implements Comparator<Student>{

@Override
public int compare(Student o1, Student o2) {
//如果id相等就认为相等,否则按照id顺序大小排序
if (o1.getId()==o2.getId()) return 0;
return o1.getId()>o2.getId()?1:-1;
}
}

//学生pojo
class Student {

private int id ;
private String name;

public Student(int id, String name) {
this.id = id;
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

以上的例子,是最简单的lambda表达式的使用方法,但也是最常用的lambda表达式使用方法, 可以极大的简化代码的冗余,好处就不用多说了。

3.Lambda表达式要注意的几个点

  •  什么样的接口我可以用lambda表达式?随便一个接口都可以么?

  JDK8之后,有一个注解为FunctionalInterface,表明的意义就是,该接口是一个函数式接口。在jdk8之后的Callable,Runnable,Comparator之中,都可以看见这个注解。可以见另一篇关于该注解的文章。

  这个问题的答案我们暂时看来是yes,我们接着继续往下走。

public class LambdaTest2 {

  //定义方法,使用到自定义的接口
public static void methodOne(String s , MyInterface myInterface){
myInterface.doSomething(s);
} public static void main(String [] args){
    //使用lambda表达式操作
methodOne("string",(s)->System.out.println(s));
} } interface MyInterface{ void doSomething(String s); }

  

  •   接口能否有多个抽象方法,如果有,lambda怎么确定实现的是什么方法?

  lambda表达式是用来简化接口的方法实现的,在不需要匿名内部类的情况下,实现一个方法。同时他也不指定方法名,那么多抽象方法的接口能使用lambda表达式么?

  如图可以看到,我们在加了注解的接口之上,写入多个抽象方法的时候,编译器会报错,即该注解只能单个抽象方法(不包含有默认实现的方法)。如果不加这个注解呢?我们知道不加注解,依然可以实现lambda表达式。让我们试一下。


我们可以看到,编译器会报错的,报错的原因其实也很简单,如果要使用这个接口的对象,那么你就要实现这个接口的所有方法,而lambda表达式只是实现了其中的一个,自然是不能使用的。

结语

  目前只是讨论了lambda表达式的开始,之后会更加深入一点理解。

最新文章

  1. C#文件目录操作完全手册
  2. Cordova应用程序修改启动画面或者Icon
  3. zookeeper、kafka、storm install
  4. POJ 1127 Jack Straws(计算几何)
  5. (原创)win7自带IIS7.5+php7.0.10安装教程(图)
  6. 【HDOJ】1494 跑跑卡丁车
  7. BestCoder Round #3HDU 4907
  8. Android简单逐帧动画Frame的实现(二)
  9. static的加载先后顺序
  10. 用PHP,怎么获取PHP.ini中的文件上传最大的字节数。也就是默认的2M
  11. IT咨询顾问:一次吐血的项目救火
  12. nsx-edge虚拟机抓包实践
  13. Docker----起步(2)----在Ubuntu上安装最新版的Docker CE
  14. 工作中常用到的Vim命令
  15. 文件操作 day8
  16. Relu的理解
  17. Banner设计的视觉导向原则分析
  18. Duplicate entry &#39;1&#39; for key &#39;PRIMARY&#39;
  19. winform ComboBox控件反选
  20. 基于 HTML5 WebGL 的 3D 风机 Web 组态工业互联网应用

热门文章

  1. 使用filebeat接收rsyslog的日志
  2. Java 函数式编程
  3. 利用ldt_struct 与 modify_ldt 系统调用实现任意地址读写
  4. 异步编程promise
  5. 微信小程序开发总结-怀庄酒业投票活动
  6. MQ的消息丢失/重复/积压的问题解决
  7. [GWCTF 2019]我有一个数据库 WP
  8. ProxySQL(10):读写分离方法论
  9. Query String Query和Sumple Query String
  10. day43-反射02