javarandom函数用法 java随机函数怎么写( 三 )
在到目前为止的示例中,流值被收集,然后被规约,但是,通常情况下,流 API 中的 Collectors 可以累积值,而不需要将它们规约到单个值 。正如下一个代码段所示,收集活动可以生成任意丰富的数据结构 。该示例使用与前面示例相同的 listOfNums:
Map<Number.Parity, List<Number>> numMap = listOfNums .parallelStream() .collect(Collectors.groupingBy(Number::getParity));List<Number> evens = numMap.get(Number.Parity.EVEN);List<Number> odds = numMap.get(Number.Parity.ODD);第一行中的 numMap 指的是一个 Map,它的键是一个 Number 奇偶校验位(ODD 或 EVEN),其值是一个具有指定奇偶校验位值的 Number 实例的 List 。同样,通过 parallelStream 调用进行多线程处理,然后 collect 调用(以线程安全的方式)将部分结果组装到 numMap 引用的 Map 中 。然后,在 numMap 上调用 get 方法两次,一次获取 evens,第二次获取 odds 。
实用函数 dumpList 再次使用来自流 API 的高阶 forEach 函数:
private void dumpList(String msg, List<Number> list) { System.out.println("\n" + msg); list.stream().forEach(n -> n.dump()); // 或者使用 forEach(Number::dump)}这是示例运行中程序输出的一部分:
The sum of the randomly generated values is: 3322The sum again, using a different method: 3322Evens:Value: 72 (parity: even)Value: 54 (parity: even)...Value: 92 (parity: even)Odds:Value: 35 (parity: odd)Value: 37 (parity: odd)...Value: 41 (parity: odd)用于代码简化的函数式结构函数式结构(如方法引用和 lambda 表达式)非常适合在流 API 中使用 。这些构造代表了 Java 中对高阶函数的主要简化 。即使在糟糕的过去,Java 也通过 Method 和 Constructor 类型在技术上支持高阶函数,这些类型的实例可以作为参数传递给其它函数 。由于其复杂性,这些类型在生产级 Java 中很少使用 。例如,调用 Method 需要对象引用(如果方法是非静态的)或至少一个类标识符(如果方法是静态的) 。然后,被调用的 Method 的参数作为对象实例传递给它,如果没有发生多态(那会出现另一种复杂性!),则可能需要显式向下转换 。相比之下,lambda 和方法引用很容易作为参数传递给其它函数 。
但是,新的函数式结构在流 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 方法在这个未命名的内部类中被重写 。
【javarandom函数用法 java随机函数怎么写】现在考虑使用新的函数式结构进行这个令人耳目一新的更改:
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 提供各种函数式接口 。以下是一些示例 。
推荐阅读
- 哪五种函数考虑左右极限
- 叫做还是叫作
- 高猛酸钾的用途和用法
- 双引号的用法及例句
- 3a香料的用法和比例是怎样的
- 连续函数乘以连续函数还连续吗
- 作贡献与做贡献区别
- 驻点和极值点的区别
- 那哪的区别及用法
- 那和哪的区别及用法
