javarandom函数用法 java随机函数怎么写( 四 )
下面的代码段介绍了参数化的 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以下是一些函数组合的样例:
int arg = 5;doubled.compose(squared).applyAsInt(arg); // 5 求 2 次方后乘 2:50tripled.compose(doubled).applyAsInt(arg); // 5 乘 2 后再乘 3:30doubled.andThen(squared).applyAsInt(arg); // 5 乘 2 后求 2 次方:100squared.andThen(tripled).applyAsInt(arg); // 5 求 2 次方后乘 3:75函数组合可以直接使用 lambda 表达式实现,但是引用使代码更简洁 。
构造器引用构造器引用是另一种函数式编程构造,而这些引用在比 lambda 和方法引用更微妙的上下文中非常有用 。再一次重申,代码示例似乎是最好的解释方式 。
考虑这个 POJO 类:
public class BedRocker { // 基岩的居民 private String name; public BedRocker(String name) { this.name = name; } public String getName() { return this.name; } public void dump() { System.out.println(getName()); }}该类只有一个构造函数,它需要一个 String 参数 。给定一个名字数组,目标是生成一个 BedRocker 元素数组,每个名字代表一个元素 。下面是使用了函数式结构的代码段:
String[] names = {"Fred", "Wilma", "Peebles", "Dino", "Baby Puss"};Stream<BedRocker> bedrockers = Arrays.asList(names).stream().map(BedRocker::new);BedRocker[] arrayBR = bedrockers.toArray(BedRocker[]::new);Arrays.asList(arrayBR).stream().forEach(BedRocker::dump);在较高的层次上,这个代码段将名字转换为 BedRocker 数组元素 。具体来说,代码如下所示 。Stream 接口(在包 java.util.stream 中)可以被参数化,而在本例中,生成了一个名为 bedrockers 的 BedRocker 流 。
Arrays.asList 实用程序再次用于流化一个数组 names,然后将流的每一项传递给 map 函数,该函数的参数现在是构造器引用 BedRocker::new 。这个构造器引用通过在每次调用时生成和初始化一个 BedRocker 实例来充当一个对象工厂 。在第二行执行之后,名为 bedrockers 的流由五项 BedRocker 组成 。
这个例子可以通过关注高阶 map 函数来进一步阐明 。在通常情况下,一个映射将一个类型的值(例如,一个 int)转换为另一个相同类型的值(例如,一个整数的后继):
map(n -> n + 1) // 将 n 映射到其后继然而,在 BedRocker 这个例子中,转换更加戏剧化,因为一个类型的值(代表一个名字的 String)被映射到一个不同类型的值,在这个例子中,就是一个 BedRocker 实例,这个字符串就是它的名字 。转换是通过一个构造器调用来完成的,它是由构造器引用来实现的:
map(BedRocker::new) // 将 String 映射到 BedRocker传递给构造器的值是 names 数组中的其中一项 。
此代码示例的第二行还演示了一个你目前已经非常熟悉的转换:先将数组先转换成 List,然后再转换成 Stream:
Stream<BedRocker> bedrockers = Arrays.asList(names).stream().map(BedRocker::new);第三行则是另一种方式 —— 流 bedrockers 通过使用数组构造器引用 BedRocker[]::new 调用 toArray 方法:
BedRocker[ ] arrayBR = bedrockers.toArray(BedRocker[]::new);该构造器引用不会创建单个 BedRocker 实例,而是创建这些实例的整个数组:该构造器引用现在为 BedRocker[]:new,而不是 BedRocker::new 。为了进行确认,将 arrayBR 转换为 List,再次对其进行流式处理,以便可以使用 forEach 来打印 BedRocker 的名字 。
推荐阅读
- 哪五种函数考虑左右极限
- 叫做还是叫作
- 高猛酸钾的用途和用法
- 双引号的用法及例句
- 3a香料的用法和比例是怎样的
- 连续函数乘以连续函数还连续吗
- 作贡献与做贡献区别
- 驻点和极值点的区别
- 那哪的区别及用法
- 那和哪的区别及用法
