java 8 stream中的Spliterator简介
java 8 stream中的Spliterator简介
简介
Spliterator是在java 8引入的一个接口,它通常和stream一起使用,用来遍历和分割序列。
只要用到stream的地方都需要Spliterator,比如List,Collection,IO channel等等。
我们先看一下Collection中stream方法的定义:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
我们可以看到,不管是并行stream还是非并行stream,都是通过StreamSupport来构造的,并且都需要传入一个spliterator的参数。
好了,我们知道了spliterator是做什么的之后,看一下它的具体结构:

spliterator有四个必须实现的方法,我们接下来进行详细的讲解。
tryAdvance
tryAdvance就是对stream中的元素进行处理的方法,如果元素存在,则对他进行处理,并返回true,否则返回false。
如果我们不想处理stream后续的元素,则在tryAdvance中返回false即可,利用这个特征,我们可以中断stream的处理。这个例子我将会在后面的文章中讲到。
trySplit
trySplit尝试对现有的stream进行分拆,一般用在parallelStream的情况,因为在并发stream下,我们需要用多线程去处理stream的不同元素,trySplit就是对stream中元素进行分拆处理的方法。
理想情况下trySplit应该将stream拆分成数目相同的两部分才能最大提升性能。
estimateSize
estimateSize表示Spliterator中待处理的元素,在trySplit之前和之后一般是不同的,后面我们会在具体的例子中说明。
characteristics
characteristics表示这个Spliterator的特征,Spliterator有8大特征:
public static final int ORDERED = 0x00000010;//表示元素是有序的(每一次遍历结果相同)
public static final int DISTINCT = 0x00000001;//表示元素不重复
public static final int SORTED = 0x00000004;//表示元素是按一定规律进行排列(有指定比较器)
public static final int SIZED = 0x00000040;//
表示大小是固定的
public static final int NONNULL = 0x00000100;//表示没有null元素
public static final int IMMUTABLE = 0x00000400;//表示元素不可变
public static final int CONCURRENT = 0x00001000;//表示迭代器可以多线程操作
public static final int SUBSIZED = 0x00004000;//表示子Spliterators都具有SIZED特性
一个Spliterator可以有多个特征,多个特征进行or运算,最后得到最终的characteristics。
举个例子
上面我们讨论了Spliterator一些关键方法,现在我们举一个具体的例子:
@AllArgsConstructor
@Data
public class CustBook {
private String name;
}
先定义一个CustBook类,里面放一个name变量。
定义一个方法,来生成一个CustBook的list:
public static List<CustBook> generateElements() {
return Stream.generate(() -> new CustBook("cust book"))
.limit(1000)
.collect(Collectors.toList());
}
我们定义一个call方法,在call方法中调用了tryAdvance方法,传入了我们自定义的处理方法。这里我们修改book的name,并附加额外的信息。
public String call(Spliterator<CustBook> spliterator) {
int current = 0;
while (spliterator.tryAdvance(a -> a.setName("test name"
.concat("- add new name")))) {
current++;
}
return Thread.currentThread().getName() + ":" + current;
}
最后,写一下测试方法:
@Test
public void useTrySplit(){
Spliterator<CustBook> split1 = SpliteratorUsage.generateElements().spliterator();
Spliterator<CustBook> split2 = split1.trySplit();
log.info("before tryAdvance: {}",split1.estimateSize());
log.info("Characteristics {}",split1.characteristics());
log.info(call(split1));
log.info(call(split2));
log.info("after tryAdvance {}",split1.estimateSize());
}
运行的结果如下:
23:10:08.852 [main] INFO com.flydean.SpliteratorUsage - before tryAdvance: 500
23:10:08.857 [main] INFO com.flydean.SpliteratorUsage - Characteristics 16464
23:10:08.858 [main] INFO com.flydean.SpliteratorUsage - main:500
23:10:08.858 [main] INFO com.flydean.SpliteratorUsage - main:500
23:10:08.858 [main] INFO com.flydean.SpliteratorUsage - after tryAdvance 0
List总共有1000条数据,调用一次trySplit之后,将List分成了两部分,每部分500条数据。
注意,在tryAdvance调用之后,estimateSize变为0,表示所有的元素都已经被处理完毕。
再看一下这个Characteristics=16464,转换为16进制:Ox4050 = ORDERED or SIZED or SUBSIZED 这三个的或运算。
这也是ArrayList的基本特征。
总结
本文介绍了跟stream息息相关的接口Spliterator,讨论了它的构成,并举例说明,希望大家能够掌握。
本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/Spliterator
欢迎关注我的公众号:程序那些事,更多精彩等着您!
更多内容请访问 www.flydean.com
java 8 stream中的Spliterator简介的更多相关文章
- java 8 Stream中操作类型和peek的使用
目录 简介 中间操作和终止操作 peek 结论 java 8 Stream中操作类型和peek的使用 简介 java 8 stream作为流式操作有两种操作类型,中间操作和终止操作.这两种有什么区别呢 ...
- Java Web开发中MVC设计模式简介
一.有关Java Web与MVC设计模式 学习过基本Java Web开发的人都已经了解了如何编写基本的Servlet,如何编写jsp及如何更新浏览器中显示的内容.但是我们之前自己编写的应用一般存在无条 ...
- java流stream中的collect()方法详解
public class StreamTest { /** * stream.collect() 的本质由三个参数构成, * 1. Supplier 生产者, 返回最终结果 * 2. BiConsum ...
- 【Java必修课】图说Stream中的skip()和limit()方法及组合使用
1 简介 本文将讲解Java 8 Stream中的两个方法:skip()和limit().这两个方法是Stream很常用的,不仅各自会被高频使用,还可以组合出现,并能实现一些小功能,如subList和 ...
- 【Java 8】Stream中flatMap方法
在java 8 Stream中,flatMap方法是一个维度升降的方法 举例说明 给 定 单 词 列 表["Hello","World"] ,要返回列表 [&q ...
- Java 8 Stream API 引入和使用
引入流 流是什么 流是Java API的新成员,它允许你以声明性的方式处理数据集合.可以看成遍历数据集的高级迭代.流可以透明地并行处理,无需编写多线程代码.我们先简单看一下使用流的好处.下面两段代码都 ...
- Java之Stream流
Stream流的初步学习 初次学习Stream流的学习笔记,学习之前先了解一下函数式接口 概述 API是一个程序向使用者提供的一些方法,通过这些方法就能实现某些功能.所以对于流API来 说,重点是怎么 ...
- java.util.stream 库简介
Java Stream简介 Java SE 8 中主要的新语言特性是拉姆达表达式.可以将拉姆达表达式想作一种匿名方法:像方法一样,拉姆达表达式具有带类型的参数.主体和返回类型.但真正的亮点不是拉姆达表 ...
- java stream中Collectors的用法
目录 简介 Collectors.toList() Collectors.toSet() Collectors.toCollection() Collectors.toMap() Collectors ...
随机推荐
- Pointer Lock API(2/3):属性、方法、事件
Pointer Lock API 提供了三个属性.两个方法.两个事件 Tabel Of Content 属性 Document.pointerLockElement Document.onpointe ...
- 今天无意中看到了str_split这个函数
前2天做广点通统计接口进行回调时需要加密,其中Python对字符串遍历很方便. s = 'abcd' for ch in s: print ch 但是PHP我想了半天还是老样子for循环之类的: &l ...
- 【php】面向过程的文件上传过程
//执行完整的文件上传 $path = "./uploads"; //文件上传的指定目录 $upfile = $_FILES['pic']; //文件的上传信息[一维数组] $ty ...
- python 函数简介
一.为什么要有函数? 不加区分地将所有功能的代码垒到一起,问题是: 代码的可读性差. 代码冗余 代码可扩展性差 如何解决? 函数即工具,事先准备工具的过程是定义函数,拿来就用指的是函数调用. 什么是函 ...
- 绕过CDN查找真实 IP 姿势总结
返回域名解析对应多个 IP 地址,网站可能部署CDN业务,我们就需要bypass CDN,去查找真正的服务器ip地址 0x01.域名搜集 由于成本问题,可能某些厂商并不会将所有的子域名都部署 CDN, ...
- 打印图片的属性和实现另存图片功能以及使用numpy
上一篇我们已经学了如何读取图片的功能了以及和opencv的环境搭建了,今天接着来学习,哈哈哈,今天刚好五一,也没闲着,继续学习. 1. 首先我们来实现打印出图片的一些属性功能, 先来看一段代码: im ...
- C - Max Sum Plus Plus HDU - 1024
用二位数组dp[i][j]记录组数为i,前j个数字的最大子段和. 转移方程: dp[i][j],考虑第j个数,第j个数可以并到前面那一组,此时dp[i][j]=dp[i][j-1]+arr[j],第j ...
- vue2.x学习笔记(九)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12577948.html. 数组的更新检测 数组在javascript是一种特殊的对象,不是像普通的对象那样通过Ob ...
- Laravel 5.7 RCE (CVE-2019-9081)
Laravel 代码审计 环境搭建 Laravel 5.7 文档 : https://learnku.com/docs/laravel/5.7/installation/2242 Composer 下 ...
- vue路由中 Navigating to current location ("/router") is not allowed
报错原因:多次点击同一路由,导致路由被多次添加 解决方法: router/index中添加以下代码: //router/index.js Vue.use(VueRouter) //导入vue路由 co ...