JavaSE 8 :Lambda 快速学习(一)

注:此文章是Orcale的Lambda教程,第一次翻译发文,翻译有不对和不妥之处多多包涵,还请及时指正以免贻笑大方。。。。

附上原文地址:点击打开链接

概述

目的

  此教程是介绍在Java SE8中新添加的lambda表达式

建议完成时间

  约一个小时

简介

        Lambda表达式是Java SE8 中新加入并且很重要的新特征,它们通过使用表达式提供了一种明确而简洁的方式来表示一个方法接口.Lambda表达式也改进了Collection库,使其从Collection遍历,过滤和抽取数据变得更加容易.另外,新的并发特征也提升在多核环境下的性能.

   该Orcale示例(原文叫Orcale byExamp简称OBE)是对JavaSE8中lambda表达式的初步介绍.在对功能接口和新的lambda语法讨论之后,又对匿名内部类做了介绍.此外对几个常见的使用模式在使用lambda表达式的和没有使用lambda表达的做了展示.

   下一部分评述一个常见的搜索用例和怎样通过使用包含lambda表达式的java代码来进行改进.另外对在java.util.function包中提供的几个常见的功能接口,如PredicateFunction做了实例展示。

     这些OBE完成了对java集合是如何通过使用lambda表达来更新的回顾。

     这些示例的源码也将提供给你。

硬件和软件需求

    下面是需要的硬件和软件的环境(注:只要支持java8的IDE都可以,个人推荐IntelliJ IDEA)

        JDK8

NetBeans7.4

先决条件

      不打算翻译

背景知识

     在Java中匿名内部类是对那些在应用中可能只会发生一次的类的一种实现。例如,在标准的Swing和JavaFx应用的一些需要对键盘和鼠标事件进行处理的事件处理器。相比于对每一个事件写一个独立的事件处理类,你可以使用如下示例的写法

JButton testButton = new JButton("Test Button");
testButton.addActionListener(new ActionListener(){
    @Override public void actionPerformed(ActionEvent ae){
         System.out.println("Click Detected by Anon Class");
      }
  });

否则,你将要给每一个事件的ActionListener实现独立的类.而这样在需要的地方创建类使得代码比较容易阅读.但这样的代码是不优雅的,因为这么多的代码其实只需要定义一个方法.

函数式接口(Functional Interfaces 也有译作功能性接口,)

如下是定义ActionListener接口的代码

package java.awt.event;   
import java.util.EventListener;
public interface ActionListener extends EventListener {
   
   public void actionPerformed(ActionEvent e);
  
}

这个ActionLisener就是只有一个方法的接口。在Java SE8中,像这样形式的接口称之为“函数式接口”。注:这种类型的接口在之前称之为单个抽象方法类型(SAM

通过匿名内部类来使用函数式接口在java中是很常见的模式。除了EventListener类,像RunnableComparator接口也是同样的使用方式。因此函数式接口都是在使用Lambda表达式中被利用到。

Lambda表达式语法

Lambda表达式能够将五行代码转换到一个单独的语句从而解决匿名内部类的蓬松度问题。这个简单的解决方案解决了由内部类引起的“垂直问题”。

Lambda表达式由三个部分组成

Argument List        Arrow Token        Body

(int x, int y)        ->        x + y

Body部分既可以是一个表达式也可以是语句块.如果是在表达式的形式,Body部分只是被简单的计算然后返回值.如果是语句块的形式,Body部分可以认为像方法体一样,return语句将控制返回给匿名方法的调用者.breakcontinue关键字处在顶层是非法的,但是允许放在循环中.如果Body部分中产生结果,那么在每条控制路径都要返回值或者抛出异常.

看下面的例子

(int x, int y) -> x + y

() -> 42

(String s) -> { System.out.println(s); }

第一个表达式带有两个整形参数,分别是xy然后Body部分使用表达式形式将返回x+y的值.

第二个表达式没有参数,也是用表达式的形式将返回整型42.

第三个表达式带有String参数,使用语句块的形式将向控制台输出这个String,没有返回值.

基本的语法都已经覆盖到了,下面看一些例子.

Lambda Example

下面是之前介绍的例子的一些常见用例

Runnable Lambda

下面是怎么使用Lambda来写Runnable

public class RunnableTest { 
   public static void main(String[] args) {
     
      System.out.println("=== RunnableTest ===");
     
     // Anonymous Runnable
     Runnable r1 = new Runnable(){
       
       @Override
       public void run(){
         System.out.println("Hello world one!");
       }
     };
     
     // Lambda Runnable
     Runnable r2 = () -> System.out.println("Hello world two!");
     
     // Run em!
     r1.run();
     r2.run();
     
   }
 }

在上面的用例,要注意都没有传递任何参数也没有返回值.RunnableLambda表达式是使用语句块形式,能够将之前的五行代码转换成一条语句.

Comparator Lambda

JavaComparator类经常在集合的排序中使用.下面的例子是一个由Person构成的ArrayList在基于surName属性来排序.

 public class Person {
   private String givenName;
   private String surName;
   private int age;
   private Gender gender;
   private String eMail;
   private String phone;
   private String address;
}   
下面的代码通过使用一个匿名内部类和两个 Lambda 表达式来运用 Comparator
 public class ComparatorTest {
 
   public static void main(String[] args) {
    
     List<Person> personList = Person.createShortList();
   
     // Sort with Inner Class
     Collections.sort(personList, new Comparator<Person>(){
       public int compare(Person p1, Person p2){
         return p1.getSurName().compareTo(p2.getSurName());
       }
     });
     
     System.out.println("=== Sorted Asc SurName ===");
     for(Person p:personList){
       p.printName();
     }
     
     // Use Lambda instead
     
     // Print Asc
     System.out.println("=== Sorted Asc SurName ===");
     Collections.sort(personList, (Person p1, Person p2) -> p1.getSurName().compareTo(p2.getSurName()));
 
     for(Person p:personList){
       p.printName();
     }
     
     // Print Desc
     System.out.println("=== Sorted Desc SurName ===");
     Collections.sort(personList, (p1,  p2) -> p2.getSurName().compareTo(p1.getSurName()));
 
     for(Person p:personList){
       p.printName();
     }
     
   }

 }

17-21行的代码可以很容易的被32行的Lambda表达式代替.我们注意到第一个Lambda表达式声明了参数类型然后传给表达式,可是正如你看到的第二个表达式一样,这是个可选的写法(也可以不写参数的类型).Lambda支持"目标类型匹配"(原文叫target typing)它将从在上下文中被使用的对象类型中推导. 因为我们需要给用通用定义的Comparator指定一个类型,编译器可以推导出这两个参数是Person类型的.

Listener Lambda

最后让我们再来回顾下这个ActionListener 例子

 public class ListenerTest {
   public static void main(String[] args) {
         
     JButton testButton = new JButton("Test Button");
     testButton.addActionListener(new ActionListener(){
     @Override public void actionPerformed(ActionEvent ae){
         System.out.println("Click Detected by Anon Class");
       }
     });
     
     testButton.addActionListener(e -> System.out.println("Click Detected by Lambda Listner"));
     
     // Swing stuff
     JFrame frame = new JFrame("Listener Test");
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.add(testButton, BorderLayout.CENTER);
     frame.pack();
     frame.setVisible(true);
     
   }
 }

注意这个Lambda表达式作为一个参数传递的,"目标类型匹配"(Target typing)可以在包括下面的一些上下文中使用:

  • 变量声明

  • Assignments

  • 返回语句

  • 数组初始化

  • 方法或者构造函数的参数

  • Lambda表示体
  • 条件表达式 ?:

  • Cast expressions

源码

 点击打开链接


未完,待续。。。。






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值