java基础-函数式编程 (2)

把泛型对应上就是方法签名Person apply(String),即传入参数String,返回类型Person。
而Person类的构造方法恰好满足这个条件,因为构造方法的参数是String,

构造方法虽然没有return语句,但它会隐式地返回this实例,类型就是Person,因此,此处可以引用构造方法。构造方法的引用写法是类名::new,因此,此处传入Person::new。

小结

FunctionalInterface允许传入:

接口的实现类(传统写法,代码较繁琐);

Lambda表达式(只需列出参数名,由编译器推断类型);

符合方法签名的静态方法;

符合方法签名的实例方法(实例类型被看做第一个参数类型);

符合方法签名的构造方法(实例类型被看做返回类型)。

FunctionalInterface不强制继承关系,不需要方法名称相同,只要求方法参数(类型和数量)与方法返回类型相同,即认为方法签名相同。

3. 使用Stream

Java从8开始,不但引入了Lambda表达式,还引入了流式API:Stream API。它位于java.util.stream包中。

简介:

创建Stream

Stream<BigInteger> naturals = createNaturalStream(); naturals.map(n -> n.multiply(n)) // 1, 4, 9, 16, 25... .limit(100) .forEach(System.out::println);

Stream的特点:

它可以“存储”有限个或无限个元素。这里的存储打了个引号,是因为元素有可能已经全部存储在内存中,也有可能是根据需要实时计算出来的。

一个Stream可以轻易地转换为另一个Stream,而不是修改原Stream本身。

真正的计算通常发生在最后结果的获取,也就是惰性计算。

通常把Stream的操作写成链式操作,代码更简洁:

createNaturalStream() .map(BigInteger::multiply) .limit(100) .forEach(System.out::println);

因此,Stream API的基本用法就是:创建一个Stream,然后做若干次转换,最后调用一个求值方法获取真正计算的结果:

int result = createNaturalStream() // 创建Stream .filter(n -> n % 2 == 0) // 任意个转换 .map(n -> n * n) // 任意个转换 .limit(100) // 任意个转换 .sum(); // 最终计算结果 3.1 创建Stream 静态方法:Stream.of()

直接用Stream.of()静态方法,传入可变参数即创建了一个能输出确定元素的Stream:

import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<String> stream = Stream.of("A", "B", "C", "D"); // forEach()方法相当于内部循环调用, // 可传入符合Consumer接口的void accept(T t)的方法引用: stream.forEach(System.out::println); } } 基于数组或Collection

第二种创建Stream的方法是基于一个数组或者Collection,这样该Stream输出的元素就是数组或者Collection持有的元素:

import java.util.*; import java.util.stream.*; public class Main { public static void main(String[] args) { Stream<String> stream1 = Arrays.stream(new String[] { "A", "B", "C" }); Stream<String> stream2 = List.of("X", "Y", "Z").stream(); stream1.forEach(System.out::println); stream2.forEach(System.out::println); } }

把数组变成Stream使用Arrays.stream()方法。

对于Collection(List、Set、Queue等),直接调用stream()方法就可以获得Stream。

上述创建Stream的方法都是把一个现有的序列变为Stream,它的元素是固定的。

静态方法:Stream.genrate(),传入Supplier

创建Stream还可以通过Stream.generate()方法,它需要传入一个Supplier对象:

Stream<String> s = Stream.generate(Supplier<String> sp);

基于Supplier创建的Stream会不断调用Supplier.get()方法来不断产生下一个元素,这种Stream保存的不是元素,而是算法,它可以用来表示无限序列。

例如,我们编写一个能不断生成自然数的Supplier,它的代码非常简单,每次调用get()方法,就生成下一个自然数:

import java.util.function.*; import java.util.stream.*; public class Main { public static void main(String[] args) { Stream<Integer> natual = Stream.generate(new NatualSupplier()); // 注意:无限序列必须先变成有限序列再打印: natual.limit(20).forEach(System.out::println); } } class NatualSupplier implements Supplier<Integer> { int n = 0; public Integer get() { n++; return n; } }

每个元素都是实时计算出来的,用的时候再算。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zypzyy.html