javarandom函数用法 java随机函数怎么写( 四 )


但是,新的函数式结构在流 API 之外具有其它用途 。考虑一个 Java GUI 程序,该程序带有一个供用户按下的按钮,例如,按下以获取当前时间 。按钮按下的事件处理程序可能编写如下:
JButton updateCurrentTime = new JButton("Update current time");updateCurrentTime.addActionListener(new ActionListener() {    @Override    public void actionPerformed(ActionEvent e) {        currentTime.setText(new Date().toString());    }});这个简短的代码段很难解释 。关注第二行,其中方法 addActionListener 的参数开始如下:
new ActionListener() {这似乎是错误的,因为 ActionListener 是一个抽象接口,而抽象类型不能通过调用 new 实例化 。但是,事实证明,还有其它一些实例被实例化了:一个实现此接口的未命名内部类 。如果上面的代码封装在名为 OldJava 的类中,则该未命名的内部类将被编译为 OldJava$1.class 。actionPerformed 方法在这个未命名的内部类中被重写 。
现在考虑使用新的函数式结构进行这个令人耳目一新的更改:
updateCurrentTime.addActionListener(e -> currentTime.setText(new Date().toString()));lambda 表达式中的参数 e 是一个 ActionEvent 实例,而 lambda 的主体是对按钮上的 setText 的简单调用 。
函数式接口和函数组合到目前为止,使用的 lambda 已经写好了 。但是,为了方便起见,我们可以像引用封装方法一样引用 lambda 表达式 。以下一系列简短示例说明了这一点 。
考虑以下接口定义:
@FunctionalInterface // 可选,通常省略interface BinaryIntOp {    abstract int compute(int arg1, int arg2); // abstract 声明可以被删除}注释 @FunctionalInterface 适用于声明唯一抽象方法的任何接口;在本例中,这个抽象接口是 compute 。一些标准接口,(例如具有唯一声明方法 run 的 Runnable 接口)同样符合这个要求 。在此示例中,compute 是已声明的方法 。该接口可用作引用声明中的目标类型:
BinaryIntOp div = (arg1, arg2) -> arg1 / arg2;div.compute(12, 3); // 4包 java.util.function 提供各种函数式接口 。以下是一些示例 。
下面的代码段介绍了参数化的 Predicate 函数式接口 。在此示例中,带有参数 String 的 Predicate<String> 类型可以引用具有 String 参数的 lambda 表达式或诸如 isEmpty 之类的 String 方法 。通常情况下,Predicate 是一个返回布尔值的函数 。
Predicate<String> pred = String::isEmpty; // String 方法的 predicate 声明String[] strings = {"one", "two", "", "three", "four"};Arrays.asList(strings)   .stream()   .filter(pred)                  // 过滤掉非空字符串   .forEach(System.out::println); // 只打印空字符串在字符串长度为零的情况下,isEmpty Predicate 判定结果为 true 。因此,只有空字符串才能进入管道的 forEach 阶段 。
下一段代码将演示如何将简单的 lambda 或方法引用组合成更丰富的 lambda 或方法引用 。考虑这一系列对 IntUnaryOperator 类型的引用的赋值,它接受一个整型参数并返回一个整型值:
IntUnaryOperator doubled = n -> n * 2;IntUnaryOperator tripled = n -> n * 3;IntUnaryOperator squared = n -> n * n;IntUnaryOperator 是一个 FunctionalInterface,其唯一声明的方法为 applyAsInt 。现在可以单独使用或以各种组合形式使用这三个引用 doubled、tripled 和 squared:
int arg = 5;doubled.applyAsInt(arg); // 10tripled.applyAsInt(arg); // 15squared.applyAsInt(arg); // 25

推荐阅读