jdk8中Spliterator的作用
//单个对元素执行给定的动作,如果有剩下元素未处理返回true,否则返回false
boolean tryAdvance(Consumer<? super T> action); //对每个剩余元素执行给定的动作,依次处理,直到所有元素已被处理或被异常终止。默认方法调用tryAdvance方法
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
} //对任务分割,返回一个新的Spliterator迭代器
Spliterator<T> trySplit(); //用于估算还剩下多少个元素需要遍历
long estimateSize(); //当迭代器拥有SIZED特征时,返回剩余元素个数;否则返回-1
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
} //返回当前对象有哪些特征值
int characteristics(); //是否具有当前特征值
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
//如果Spliterator的list是通过Comparator排序的,则返回Comparator
//如果Spliterator的list是自然排序的 ,则返回null
//其他情况下抛错
default Comparator<? super T> getComparator() {
throw new IllegalStateException();
}
static final class ArrayListSpliterator<E> implements Spliterator<E> {
//用于存放ArrayList对象
private final ArrayList<E> list;
//起始位置(包含),advance/split操作时会修改
private int index;
//结束位置(不包含),-1 表示到最后一个元素
private int fence;
//用于存放list的modCount
private int expectedModCount; ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list;
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
//获取结束位置(存在意义:首次初始化石需对fence和expectedModCount进行赋值)
private int getFence() {
int hi;
ArrayList<E> lst;
//fence<0时(第一次初始化时,fence才会小于0):
if ((hi = fence) < 0) {
//list 为 null时,fence=0
if ((lst = list) == null)
hi = fence = 0;
else {
//否则,fence = list的长度。
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}
//分割list,返回一个新分割出的spliterator实例
public ArrayListSpliterator<E> trySplit() {
//hi为当前的结束位置
//lo 为起始位置
//计算中间的位置
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
//当lo>=mid,表示不能在分割,返回null
//当lo<mid时,可分割,切割(lo,mid)出去,同时更新index=mid
return (lo >= mid) ? null :
new ArrayListSpliterator<E>(list, lo, index = mid, expectedModCount);
}
//返回true 时,只表示可能还有元素未处理
//返回false 时,没有剩余元素处理了。。。
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
//hi为当前的结束位置
//i 为起始位置
int hi = getFence(), i = index;
//还有剩余元素未处理时
if (i < hi) {
//处理i位置,index+1
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)list.elementData[i];
action.accept(e);
//遍历时,结构发生变更,抛错
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
//顺序遍历处理所有剩下的元素
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst; Object[] a;
if (action == null)
throw new NullPointerException();
if ((lst = list) != null && (a = lst.elementData) != null) {
//当fence<0时,表示fence和expectedModCount未初始化,可以思考一下这里能否直接调用getFence(),嘿嘿?
if ((hi = fence) < 0) {
mc = lst.modCount;
hi = lst.size;
}
else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
//调用action.accept处理元素
action.accept(e);
}
//遍历时发生结构变更时抛出异常
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
} public long estimateSize() {
return (long) (getFence() - index);
} public int characteristics() {
//打上特征值:、可以返回size
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
public class Atest {
AtomicInteger count = new AtomicInteger(0);
List<String> strList = createList();
Spliterator spliterator = strList.spliterator(); /**
* 多线程计算list中数值的和
* 测试spliterator遍历
*/
@Test
public void mytest(){
for(int i=0;i<4;i++){
new MyThread().start();
}
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结果为:" + count);
} class MyThread extends Thread{
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("线程"+threadName+"开始运行-----");
spliterator.trySplit().forEachRemaining(new Consumer() {
@Override
public void accept(Object o) {
if(isInteger((String)o)){
int num = Integer.parseInt(o +"");
count.addAndGet(num);
System.out.println("数值:"+num+"------"+threadName);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
System.out.println("线程"+threadName+"运行结束-----");
}
} private List<String> createList(){
List<String> result = new ArrayList<>();
for(int i=0; i<100; i++){
if(i % 10 == 0){
result.add(i+"");
}else{
result.add("aaa");
}
}
return result;
} public static boolean isInteger(String str) {
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
return pattern.matcher(str).matches();
}
}
jdk8中Spliterator的作用的更多相关文章
- JDK8中的新特性
1.lambda表达式 1.定义 Java 8 发布的最重要新特性.Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),可以推导出来的就可以省略了,Lambda 表达式免去了使用匿 ...
- JDK8中Stream使用解析
JDK8中Stream使用解析 现在谈及JDK8的新特新,已经说不上新了.本篇介绍的就是Stream和Lambda,说的Stream可不是JDK中的IO流,这里的Stream指的是处理集合的抽象概念『 ...
- web.xml中load-on-startup的作用
如下一段配置,熟悉DWR的再熟悉不过了:<servlet> <servlet-name>dwr-invoker</servlet-name> <ser ...
- C#中构造函数的作用
C#中构造函数的作用 共同点: 都是实例化对象,初始化数据的 默认构造是说所有的类都从祖先object那继承了空参的构造方法,你不写与写空参构造都存在,而有参数的构造一般是自己写的,写就有不写就没有, ...
- MySQL数据库中delimiter的作用概述
以下的文章主要是向大家描述的是MySQL数据库中delimiter的作用是什么?我们一般都认为这个命令和存储过程关系不大,到底是不是这样的呢?以下的文章将会给你相关的知识,望你会有所收获. 其实就是告 ...
- js中getBoundingClientRect的作用及兼容方案
js中getBoundingClientRect的作用及兼容方案 1.getBoundingClientRect的作用 getBoundingClientRect用于获取某个html元素相对于视窗的位 ...
- Linq中关键字的作用及用法
Linq中关键字的作用及用法 1.All:确定序列中的所有元素是否都满足条件.如果源序列中的每个元素都通过指定谓词中的测试,或者序列为空,则为 true:否则为 false. Demo: 此示例使用 ...
- JAVA中protected的作用
JAVA中protected的作用 1.public:public表明该数据成员.成员函数是对所有用户开放的,所有用户都可以直接进行调用 2.private:private表示私有,私有的意思就是 ...
- url中#号的作用
url中#号的作用就是本页面位置跳转 比如这个url地址:http://www.aaaaa.com/index.html?ad=34&m=c#red red就是index.html页面的依哥位 ...
随机推荐
- POJ1182:食物链(并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 94930 Accepted: 28666 Description ...
- Windows Server 2008 R2 Upgrade Paths
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd ...
- node读取文件夹名
const fs = require('fs'); const join = require('path').join; /** * * @param startPath 起始目录文件夹路径 * @r ...
- springmvc4+hibernate4+activiti5.18(Maven)
项目下载地址: http://files.cnblogs.com/files/walk-the-Line/springmvc_activiti5.18_hibernate4.zip
- MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致
MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致 情景:当数据库中的列名与我们程序实体类中的字段名称不一致 使用ResultMap节点配置信息 在映射文件中 ...
- Ubuntu 15.10 安装比特币客户端
下载 git clone https://github.com/bitcoin/bitcoin.git cd bitcoin ./autogen.sh 安装依赖包: ++-dev sudo apt-g ...
- JavaScript设置获取和设置属性的方法
这篇文章主要介绍了JavaScript设置获取和设置属性的方法,学会使用getAttribute.setAttribute的用法,需要的朋友可以参考下 getAttribute 该方法用来获取元素 ...
- [Leetcode Week2]Merge Intervals
Merge Intervals题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/merge-intervals/description/ Descript ...
- SQL按多个字段排序时的实现规则
1.在使用SQL中的ORDER BY按照表中的多个列对表做排序是,会按照第一个列的排序条件作为排序基准,当第一个列的值都相同时,才会按照后面的列的排序条件作为排序基准: 案例如下: 图一和图二展示的是 ...
- linux常用命令 查看文件
Linux常用命令 查看文件 cat命令 cat命令的用途是连接文件或标准打印输入并打印.这个命令常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示. 命令格式: cat [ ...