第六章 lambda表达式

lambda的语法

  • 只有一个参数时,可省略前面的小括号
  • 如果要执行的代码块多于一个表达式,那么用{}括起来
  • 若可以推导出参数类型,那么可以忽略其类型。
  • 无需指定lambda表达式的返回类型因为总是可以从上下文推导得出。

注意,不可以在一些分支返回值,领一下额分支不返回值。
一个栗子:

package lambda;
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);         
   }
}

注意上面例子中的两个lambda表达式的巧妙应用。

函数式接口

最好把lambda表达式看作是一个函数而不是一个对象。
不能把lambda表达式赋值给类型为Object的变量,Object不是一个函数式接口。

许多接口往往有一个特定的用途,而不只是提供一个有指定参数和返回类型的方法。类似于Comparator。java.util.function包中有一个特别有用的接口Predicate:

public interface Predicate<T>{
	boolean test(T t);
}
list.removeIf(e->e==null)//delete all null in list;

余以为此处不易理解。
解释:
此处removeIf函数的参数是一个Predicate,这个接口专门用来传递lamda表达式。

方法引用

方法引用于lambda表达式均不能独立存在,两者都会转化为函数式接口的实例。

语法:
用 :: 分割方法名与对象名或类名。

有三种情况:
object::instanceMethod
Class::staticMethod
Class::instanceMethod
说明:对于第三种情况,第一个参数会成为方法的目标。

this::equals <=> x->this.equals(x)
更有super::greet() 将使用this作为目标,调用方法的超类版本。

构造器引用 P237

与方法引用类似,不同:方法名是new

也可以用数组类型建立构造器引用,int[]::new 等价于 x->new int[x]

数组构造器引用 解决了无法构造泛型类型T的数组:
(然而不太理解应用场景)

Object[]people=stream.toArray();

Object[]people=stream.toArray(Person[]::new);

变量的作用域

希望在lambda表达式中访问外围方法或类中的变量。

  • **规则:**lambda表达式中捕获的变量必须是最终变量,不能改变。
  • 同样适用于命名冲突和遮蔽的有关规则。

处理lambda表达式

如何编写一个方法处理lambda表达式???
使用lambda表达式的重点是延迟执行。

函数要想接受一个lambda表达式,需要选择一个函数式接口。
eg:

public static void repeat(int n,Runnable action)
{
for (int i=0;i<n;i++) action.run();
}
//如何调用repeat呢???
注意 ==第二个参数是一个lambda表达式==
repeat(10,()->System.out.println("HEllo!"))

在处理问题时,选取合适的函数式接口很重要。P240

再谈comparator接口

Comparator接口包含很多方便的静态方法创建比较器。这些方法可以用于lambda表达式或方法引用。


Arrays.sort(people,Comparator.comparing(Person::getName));

Arrays.sort(people,Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstname));

Arrays.sort(people,Comparator.comparing(Person::getName,(s,t)->Integer.compare(s.len-t.len)));

Arrays.sort(people,Comparator.comparingInt(p->p.getName().length()));

Arrays.sort(people,Comparator.comparing(Person::getMiddleName,nullsFirst(naturalOrder())));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值