6.3 Lambda表达式

来源:互联网 发布:qq主题下载软件 编辑:程序博客网 时间:2024/06/18 17:00

关于Lambda这块,我理解不了…所以多去看看别人的讲解吧…


使用lambda表达式可以用简明的语法定义一个块的代码。


1 什么是Lambda表达式?

Lambda表达式是一个块的代码,定义完毕后,马上就会使用的式子。
这是Java SE 8的新增内容。


2 Lambda表达式的语法

//比较两个字符串的长度(String first, String second) ->    {        if (first.length() < second.length()) return -1;        else if (first.length() > second.length()) return 1;        else return 0;    }
//输出100~0() -> { for (int i = 100; i >= 0; i--) System.out.println(i); }
//Lambda表达式赋值给一些特定变量,这里连String都省略了Comparator<String> comp    = (first, second) // Same as (String first, String second)                -> first.length() - second.length();
//这个连小括号都省略了ActionListener listener = event ->    System.out.println("The time is " + new Date());    // Instead of (event) -> . . . or (ActionEvent event) -> . . .

示例

import java.util.*;import javax.swing.*;import javax.swing.Timer;public class LambdaTest{   public static void main(String[] args)   {      String[] planets = new String[] { "Mercury", "Venus", "Earth", "Mars",             "Jupiter", "Saturn", "Uranus", "Neptune" };      System.out.println(Arrays.toString(planets));      System.out.println("Sorted in dictionary order:");      Arrays.sort(planets);      System.out.println(Arrays.toString(planets));      System.out.println("Sorted by length:");      Arrays.sort(planets, (first, second) -> first.length() - second.length());      System.out.println(Arrays.toString(planets));      Timer t = new Timer(1000, event ->         System.out.println("The time is " + new Date()));      t.start();         // keep program running until user selects "Ok"      JOptionPane.showMessageDialog(null, "Quit program?");      System.exit(0);            }}

3 函数式接口

Arrays.sort(planets, (first, second) -> first.length() - second.length());

这里sort方法的第二个参数要求是一个实现Comparaor接口的实例。

//这是Comparator接口声明的方法,上面的Lambda表达式直接作为该方法的方法体执行了int compare(T o1, T o2);

学习Lambda的难点是,Lambda表达式不是对象,而是函数。或者更具体的说,上面的sort方法想要传入 的参数并不是那个Comparator对象的实例,而是其compare方法的计算方法。
可以看出,使用Lambda表达式,大大简化了代码的长度,简洁明了。这是函数式编程的优点。

//这是另一个例子,对ActionListener接口的Lambda改写Timer t = new Timer(1000, event ->    {        System.out.println("At the tone, the time is " + new Date());        Toolkit.getDefaultToolkit().beep();    });

在java.util.function包,有大量的函数式接口。

//这个接口就声明了输入两个字符串返回一个整型的函数接口BiFunction<String, String, Integer> comp = (first, second) -> first.length()- second.length();
public interface Predicate<T>{    boolean test(T t);    // Additional default and static methods}
//ArrayList里面的removeIf方法就接受一个Predicate参数,采用如下Lambda表达式就能把,所有null元素删除list.removeIf(e -> e == null)

4 方法引用

::操作符表示直接传入一个方法作为方法体。

//用Lambda表达式,一旦产生了一个ActionEvent就会执行后面的Lambda方法Timer t = new Timer(1000, event -> System.out.println(event));
//这是采用::操作符的结果,把println方法传入,用来替代原本的对ActionEvent操作方法Timer t = new Timer(1000, System.out::println);
  1. 原本的Timer传入的参数是一个ActionListener接口,意思是,一旦有事件发生,把这个事件ActionEvent传入ActionListener接口的方法actionPerformed,执行这个方法的方法体。
  2. Lambda表达式说,不就是想对ActionEvent执行一系列操作嘛,我直接给你操作方法,免得在去定义什么接口实例了。
  3. ::操作符说,不就是想要方法嘛,我直接给你一个方法,给你执行好了。

下面是::操作符的用法:
对象::实例方法
类::静态方法
类::实例方法//这个的意思是把第一个参数当作实例,例:String::compareTo的意思是(x,y)->x.compareTo(y)

同样的,this和super关键字也同样能用。


5 构造器引用

这个就是把构造器当作引用传入呗,和上面的没区别,只是用new代替方法名称而已。

ArrayList<String> names = . . .;Stream<Person> stream = names.stream().map(Person::new);//等同于调用 new Person(String)List<Person> people = stream.collect(Collectors.toList());

数组也可以,

int[]::new //传入一个数字作为数组的长度嘛

仅限于基本类型哦,除非你有指定类型

Object[] people = stream.toArray();//返回一个Object[]Person[] people = stream.toArray(Person[]::new);//返回一个Person[]

6 变量范围

public static void repeatMessage(String text, int delay){    ActionListener listener = event ->        {            System.out.println(event);            System.out.println(text);            Toolkit.getDefaultToolkit().beep();        };    new Timer(delay, listener).start();}
repeatMessage("Hello", 1000); // Prints Hello every 1,000 milliseconds

上面的示例,Lambda表达式使用了一个局部变量作为参数。
重新定义Lambda表达式:

  1. 是一系列执行代码
  2. 会输入参数,例如:event
  3. 使用自由参数,例如:text//注意,这个自由参数必须是不可变的参数,否则Lambda表达式的执行就可能出现不同的结果,这是不允许的,线程不安全嘛,,可以定义final,然后就可以了
Path first = Paths.get("/usr/bin");Comparator<String> comp =(first, second) -> first.length() - second.length();// 错误的Lambda表达式,first已经被定义了

7 审查Lambda表达式

  1. 要分离线程时候使用
  2. 在多个时间要运行
  3. 在算法的指定点运行
  4. 某些事件发生时运行
  5. 有必要才运行

8 关于Comparators

介绍了一些比较的Lambda表达式写法,,,我要晕了,我不写了,,,挺难的,一下子学习那么多,,,

0 0
原创粉丝点击