为什么?
   我们为什么需要Lambda表达式
   主要有三个原因:
   > 更加紧凑的代码
     比如Java中现有的匿名内部类以及监听器(listeners)和事件处理器(handlers)都显得很冗长
   > 修改方法的能力(我个人理解为代码注入,或者有点类似JavaScript中传一个回调函数给另外一个函数)
     比如Collection接口的contains方法,当且仅当传入的元素真正包含在集合中,才返回true。而假如我们想对一个字符串集合,传入一个字符串,只要这个字符串出现在集合中(忽略大小写)就返回true。
     简单地说,我们想要的是传入“一些我们自己的代码”到已有的方法中,已有的方法将会执行我们传入的代码。Lambda表达式能很好地支持这点
   > 更好地支持多核处理
     例如,通过Java 8新增的Lambda表达式,我们可以很方便地并行操作大集合,充分发挥多核CPU的潜能。
     并行处理函数如filter、map和reduce。

怎么做?
   实例1 FileFilter

File dir = new File("/an/dir/");
FileFilter directoryFilter = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};

通过Lambda表达式这段代码可以简化为如下:

File dir = new File("/an/dir/");
FileFilter directoryFilter = (File f) -> f.isDirectory();
File[] dirs = dir.listFiles(directoryFilter);

进一步简化:

File dir = new File("/an/dir/");
File[] dirs = dir.listFiles((File f) -> f.isDirectory());

Lambda表达式使得代码可读性增强了。我承认我开始学习Java的时候对那个匿名内部类感到很困扰,而现在Lambda表达式让这一切看起来都很自然(尤其是有.NET背景的童鞋会发现这个跟.NET中的Lambda表达式好像)

Lambda表达式利用了类型推断(type inference)技术:

编译器知道FileFilter只有一个方法accept(),所以accept()方法肯定对应(File f) -> f.isDirectory()
而且accept()方法只有一个File类型的参数,所以(File f) -> f.isDirectory()中的File f就是这个参数了,
.NET把类型推断做得更绝,如果上面用.NET Lambda表达式写法的话是这样的:
File[] dirs = dir.ListFiles(f => f.isDirectory());
即压根就不需要出现File类型指示。

实例2 Event Handler

Button bt = new Button();
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ui.showSomething();
}
});

使用Lambda表达式后:

Button bt = new Button();
ActionListener listener = event -> { ui.showSomething(); };
bt.addActionListener(listener);

进一步简化:

Button bt = new Button();
bt.addActionListener(event -> { ui.showSomething(); });

外循环、内循环和Map、Reduce、Filter
   一直到现在,处理Java集合的标准做法是采用外循环。比如:

List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
for(int item: list) {
// 处理item
}

还有迭代器循环,它们都是外循环,并且都是顺序处理(sequential handling)。顺序特性也常常引发ConcurrentModificationException,只要我们尝试着并发修改集合。
   Lambda表达式提供了内循环机制。

我们工作中可能经常面临下面的需求:

> 过滤掉一个集合中不符合条件的元素得到一个新集合
> 对集合中的每个元素进行某种转换,并且对转换后的集合进行处理
> 统计整个集合的某个属性,比如统计集合元素值的总和或平均值

这些任务即filter、map和reduce,他们的共同特点是:
   需要对集合中的每个元素运行一小段相同的代码。

传统的实现这些任务的代码让人感到很乏味,幸运的是Java 8提供了完成这些任务的更简洁的方案,当然还是利用Lambda表达式,但也引入了一个新的类库java.util.functions,包含Predicate、Mapper和Block。

Java 8中,一个Predicate(谓词)是这样一个方法:它根据变量的值进行评估(evaluate),返回true或false。

比如下面:

List<String> list = getMyStrings();
for(String myString: list) {
if(myString.contains(possible)) {
System.out.println(myString + " contains " + possible);
}
}

使用Predicate和Filter后得到下面代码:

List<String> list = getMyStrings();
Predicate<String> matched = s -> s.equalsIgnoreCase(possible);
list.filter(matched);

进一步简化:

List<String> list = getMyStrings();
list.filter(s -> s.equalsIgnoreCase(possible));

Lambda表达式语法规则
   到目前为止Java 8中的Lambda表达式语法规则还没有完全确定。

但这里简单介绍下:

对于前面的:

File dir = new File("/an/dir/");
File[] dirs = dir.listFiles((File f) -> f.isDirectory());

accept()方法返回布尔值,这种情况f.isDirectory()显然也得是布尔值。这很简单。
   而对于:

Button bt = new Button();
bt.addActionListener(event -> { ui.showSomething(); });

actionPerformed()方法的返回类型是void,所以需要特殊处理,即在ui.showSomething();左右加上花括号。(想象下 不加会怎么样?如果不加的话,若showSomething()方法返回值是整数类型,那么就意味着actionPerformed()返回整数类型,显 然不是,所以必须加花括号用来标记)。
   如果Lambda表达式主体部分包含多条语句,也必须用花括号,并且return语句不能省。

比如下面这个:

File dir = new File("/an/dir/");
File[] dirs = dir.listFiles((File f) -> {
System.out.println("Log:...");
return f.isDirectory();
}
);

参考自:http://www.oraclejavamagazine-digital.com/javamagazine/20121112?sub_id=hlBuL1SAFxXX#pg35

最新文章

  1. SCNU ACM 2016新生赛决赛 解题报告
  2. 简单的数据库设计及使用(FMDB)
  3. 4 Best Time to Buy and Sell Stock III_Leetcode
  4. 后缀数组 - 求最长回文子串 + 模板题 --- ural 1297
  5. 编译项目报错: Ignoring file / xxx , missing required architecture i386 in file / xxx (2 slices)
  6. Oracle中如何判断一个字符串是否含有汉字
  7. 一步一步写算法(之hash表)
  8. POJ_3046_Ant_Counting_(动态规划,多重集组合数)
  9. [Android] Service和IntentService中显示Toast的区别
  10. Swift初体验(两)
  11. 05 Activity知识
  12. NewLife.Net——构建可靠的网络服务
  13. CoCos2dx开发:更换导出的app名称和图标
  14. j假设程序需要要一个int烈血的刀变量来保存1英里所包含的步数(5280)为该变量编写一条声明语句。
  15. MapReduce分组
  16. function [eigf,eigv,dof]=laplaceeig(node,elem,problem)
  17. OpenFileDialog 打开文件
  18. 【luogu P1156 垃圾陷阱】 题解
  19. IE中iframe兼容性问题
  20. (转)linux sed命令就是这么简单

热门文章

  1. div滚动到页面顶端后固定住
  2. arcgis 栅格计算器(Spatial Analyst/Raster Calculator)
  3. iOS 播放声音文件
  4. nginx/Windows-1.9.0的日志分割
  5. (转)log4net的配置详解
  6. 01-CALayer的基本操作
  7. Virtualenv介绍
  8. Android开发-API指南-&lt;instrumentation &gt;
  9. Flex Alert的匿名回调函数如何得到正确的this
  10. Hibernate 常见异常