vlambda博客
学习文章列表

Java8实践指南(三) 代表性的函数式接口

代表性的函数式接口

在深入探讨流之前,让我们先了解函数式接口。正如在前面中讨论过的,函数式接口是包含单个抽象方法声明(SAM)的接口Java SE 8在 java.util.function包中添加了43个通用的函数式接口。从理论上来讲lambda表达式表示的函数对象通常是这43个函数式接口的对象之一(当然,其他函数式接口类型也有,比如Comparator)。


这是否意味着必须了解所有的43个接口呢? 答案当然不是,这里面只有7个接口是非常重要的,需要我们熟练掌握。其余的只是这7个接口的变形版本(派生类型和基本数据类型)。让我们学习一下这7个代表性的函数式接口。


Supplier<T>

Supplier<T>接口具有抽象方法"T get()"作为SAM(唯一抽象方法),该方法不带参数,返回T类型的值。英语单词"Supplier"表示"供应商",它表示从无到有创建对象的函数。Stream接口具有使用Supplier<T>接口类型作为参数的generate()方法和collect()方法。下面是使用generate()方法的示例代码。generate()方法是Stream接口的静态方法。

Stream<Double> stream = Stream.generate(()-> Math.random());


generate()方法的参数使用lambda表达式"()-> Math.random()"。也可以使用方法引用"Math:random()"作为参数Math类的random()方法随机返回大于等于0.0,小于1.0的双精度值。generate()方法无限次调用Math类的random()方法,并生成所谓的"无限顺序流"。换句话说,它是一个在概念上具有无限数据的流。实际应用中,经常使用Stream接口的limit()方法限定特定数量的元素。

Stream<Double> stream = Stream.generate(()-> Math.random()) .limit(10000000);


上面的示例代码生成一个流对象,该对象具有1亿个随机值,这些值大于等于0.0,小于1.0。作为此接口的基础数据类型的特定版本(T是基础数据类型的版本),有以下变形版本

BooleanSupplier接口

IntSupplier接口

LongSupplier接口

DoubleSupplier接口 

 

Consumer<T>接口

Consumer<T>接口具有抽象方法"void accept(T t)"作为SAM,该方法接受T类型的参数,对其执行某些操作,无返回值。英语单词"Consumer"表示"消费者",它表示一个函数,该函数仅消费作为参数接收的对象,而不返回任何值。与前面介绍的Supplier<T>接口完全相反。

Stream接口具有使用Consumer接口类型作为参数的forEach()和peek()方法。下面是使用forEach()方法的示例代码。

List<String> list = Arrays.asList("A", "B", "C");list.stream().forEach(System.out::println);


forEach()方法对流对象具有的单个对象执行某些操作(消费)。示例代码中消费对象的操作是将其值输出到标准输出。执行标准输出的System.out对象的println()方法通常只是在显示器上显示值,而返回类型是void类型。上述示例代码与以下传统思路的代码相同∶

List<String> list = Arrays.asList("A", "B", "C");for(String s : list){ System.out.println(s);}


作为此接口的基础数据类型特定版本(T部分是基础数据类型的版本),有以下变形版本:

IntConsumer接口

LongConsumer接口

DoubleConsumer接口

它还有接受两个参数的变形版本

BiConsumer<T,U>

进一步,还有以下基础数据类型的变形版本,这些接口接受两个参数∶引用类型和基础数据类型

ObjIntConsumer接口

ObjLongConsumer接口

ObjDoubleConsumer接口