java 数据流分类_java8实战读书笔记:数值流、Stream创建与Optional类的使用

本节将详细介绍Java8中的数值流、流的创建与Optional类的使用。

数值流

不知大家还记不得,在介绍函数式编程接口中为了避免基础数据类型的装箱/拆箱带来的性能损耗,特意为函数式接口引入了基础数据类型的函数式编程接口,例如IntPredicate、LongPredicate、DoublePredicate。同样,流API也考虑到基本数据类型的装箱/拆箱会带来性能损耗,引入了数值流,例如IntStream、LongStream、DoubleStream。

1.1 原始数据特化流

java8中提供了3个原始数据特化流,分别为IntStream、LongStream、DoubleStream。本文将以IntStream进行讲解,其他流类似,只是数据类型分别代表Long或Double。

1.1.1 映射到数据流

首先我们还是从一个示例开始本节的学习:计算菜单中所有菜品的卡路里之和。

public static void test_reduce_caluli(List menu){

int calories = menu.stream()

0, Integer::sum);

"菜品中的总卡路里:" + calories);

上面包含了一个基本数据类型的装箱/拆箱动作,java8的流API提供了mapToInt方法,直接返回int类型的流

我们先稍微看一下mapToInt的方法声明:

IntStream mapToInt(ToIntFunction super T> mapper)

接受一个T->int的函数式编程接口,直接返回IntStream流对象,而且IntStream本身提供了一些常用的聚合函数,例如sum。

使用IntStream来实现计算菜单中所有菜品的卡路里之和,其示例如下:

public static void test_reduce_caluli_intStream(List menu){

int calories = menu.stream()

"菜品中的总卡路里:" + calories);

1.1.2 转换回对象流

使用了特化流例如IntStream后,将不能再自动转换为其对应的封装对象流Stream< T >了,我们可以随意从IntStream对象中对应的通用方法的函数声明,例如IntStream#map函数的声明如下:

IntStream map(IntUnaryOperator mapper);

只能接受int -> int的函数式编程接口,如果想将IntStream转回到Stream< Integer >,该如何处理呢?

IntStream提供了boxed()方法来实现将基础数据类型转换回对应的包装类型的流。

1.1.3 常用函数

Stream中定义的方法,IntStream也可以使用,例如map、flatMap、distinict等,IntStream除这些之外,还提供了常用的聚合函数,例如sum、min、max、average(平均数)。

OptionalDouble average();

OptionalInt max();

OptionalInt min();

int sum();

有关Optional相关的类将在下文详细介绍。

另外除了上面提到的聚合函数,IntStream还提供了两个与数值范围的方法:

public static IntStream range(int startInclusive, int endExclusive);

public static IntStream rangeClosed(int startInclusive, int endExclusive);

rangeClosed与range的区别就是rangeClosed包含结束边界,举一个简单示例如下:

public static void test_range(){

long count = IntStream.range(1,100)

2 == 0 )

"count:" + count);

计算【1,100)中包含的偶数个数,将输出49。如果将range(1,100)修改为rangeClosed(1,100),在输出的个数为50。

构建流

2.1 通过值构建流

java 8的Stream提供了两个重载的of函数来显示的构建流,其声明如下:

public static Stream of(T t)

public static Stream of(T... values)

2.2 通过数组构建流

通过Arrays.stream构建流,其声明如下:

Arrays#stream

public static  Stream stream(T[] array)

2.3 通过文件流

可以通过文件流创建流,在java.nio.file.Files类中定义了如下创建流的方法。

public static Stream list(Path dir) throws IOException

public static Stream walk(Path start, int maxDepth, FileVisitOption... options)

public static Stream walk(Path start, FileVisitOption... options)

public static Stream find(Path start, int maxDepth,BiPredicate matcher,

public static Stream lines(Path path, Charset cs)

public static Stream lines(Path path) throws IOException

下面我们举一个示例:找出一个文件中不同词的个数。

public static void test_file_stram(){

long uniqueWords = 0;

try(Stream lines = Files.lines(Paths.get("d:/tmp/words.txt"), Charset.defaultCharset())) {

"" )))

"不重复字符个数:" + uniqueWords);

catch (IOException e) {

2.4 函数生成流:创建无限流

Stream API提供了两个静态方法从函数生成流:iterate、generate,我们先来看一下其函数声明:

public static Stream iterate(final T seed, final UnaryOperator f)

public static Stream generate(Supplier s)

2.4.1 iterate

iterate方法的第一个参数类型为T,表示其初始值,第二个参数如下:

32a43124a4b83109d1be2ca5eb991166.png

即其函数式声明为为T-T。其示例如下:

public static void test_iterate(){

0, a -> a + 2)

10)

注意:由于是无限流,故千万记得使用limit截断流,否则会无限循环下去。

2.4.2 generate

其参数为Supplier< T >,其定义如下:

cf596b7d965dd3a8b7be00df97e7b9e8.png

即构造一个T类型的对象,举例如下:

public static void test_iterate(){

0, a -> a + 2)

10)

2.5 集合对象的stream

这个在前面的示例中用的最多,就不做过多介绍。

Optional类

为了更优雅的处理null值,避免空指针错误,java8中引入Optional类。

8ee82565f3da2df302a6d9a127a2e960.png

接下来对这些方法一一做个介绍。

public static< T> Optional< T> empty()

创建一个Optional对象,其内部持有的对象为null。

public static < T > Optional< T > of(T value)

使用value的值,创建一个Optional对象。

public static < T > Optional< T > ofNullable(T value)

使用v去创建一个Optional对象,如果value为null,则返回empty()。

public T get()

从Optional对象获取内嵌的对象,如果为空,则抛出NoSuchElementException。

public boolean isPresent()

判断Optional对象中包含的值是否存在。

public void ifPresent(Consumer consumer)

如果Optional包裹的对象存在,则消费该对象。Consumer的函数式编程接口:T -> void。

public Optional< T > filter(Predicate predicate)

如果Optional中包裹的对象为空,则返回自身,否则如果包裹的对象满足predicate表达式,则返回自身,否则返回empty()。

public< U > Optional< U > map(Function mapper)

如果Optional对象中包裹的对象为空,则返回empty(),否则运用(T-U),包裹U,当然如果U为空,则返回empty()。

public< U > Optional< U > flatMap(Function> mapper)

如果Option对象中包裹的对象为空,则返回empty(),否则使用对Optional中的包裹的对象value应用Function,最终返回Optional对象。

public T orElse(T other)

返回Optional中包裹的对象,如果其值为空,则返回other。

public T orElseGet(Supplier other)

返回Optional中包裹的对象,如果其值为空,则返回 Supplier函数式编辑接口中创建的值。

public < X extends Throwable> T orElseThrow(Supplier< ? extends X> exceptionSupplier) throws X

返回Optional中包裹的对象,如果其值为空,则抛出自定义一次,由Supplier函数式编程接口返回。

其示例代码如下:public static void test_option(){

new HashMap<>();

"userName"));

// 如果存在userName值,则输出

本文就介绍到这里了,本文详细介绍了java8中的数值流、Stream的创建以及java8中Optional类的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值