文章前半部分转自:https://blog.csdn.net/lh513828570/article/details/56673804
###Spliterator是什么?
public interface Spliterator
Spliterator是一个可分割迭代器(splitable iterator)
,可以和iterator顺序遍历迭代器一起看。jdk1.8发布后,对于并行处理的能力大大增强,Spliterator就是为了并行遍历元素而设计的一个迭代器,jdk1.8中的集合框架中的数据结构都默认实现了spliterator,后面我们也会结合ArrayList中的spliterator()
一起解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| boolean tryAdvance(Consumer<? super T>action);
default void forEachRemaining(Consumer<? super T>action){ do{}while(tryAdvance(action)); }
Spliterator<T> trySplit();
long estimateSize();
default long getExactSizeIfKnown(){ return(characteristics()&SIZED)==0?-1L:estimateSize(); }
int characteristics();
default boolean hasCharacteristics(int characteristics){ return(characteristics()&characteristics)==characteristics; }
default Comparator<? super T>getComparator(){ throw new IllegalStateException(); }
|
特征值其实就是为表示该Spliterator有哪些特性,用于可以更好控制和优化Spliterator的使用。关于获取比较器getComparator这一个方法,目前我还没看到具体使用的地方,所以可能理解有些误差。(源玛里有这里就不展示了)
###ArrayList的例子
ArrayListSpliterator在ArrayList的源码里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| static final class ArrayListSpliterator<E> implements Spliterator<E> { private final ArrayList<E> list; private int index; private int fence; 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; }
private int getFence() { int hi; ArrayList<E> lst; if ((hi = fence) < 0) { if ((lst = list) == null) hi = fence = 0; else { expectedModCount = lst.modCount; hi = fence = lst.size; } } return hi; }
public ArrayListSpliterator<E> trySplit() { int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; return (lo >= mid) ? null : new ArrayListSpliterator<E>(list, lo, index = mid, expectedModCount); }
public boolean tryAdvance(Consumer<? super E> action) { if (action == null) throw new NullPointerException(); int hi = getFence(), i = index; if (i < hi) { 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; ArrayList<E> lst; Object[] a; if (action == null) throw new NullPointerException(); if ((lst = list) != null && (a = lst.elementData) != null) { 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(e); } if (lst.modCount == mc) return; } } throw new ConcurrentModificationException(); }
public long estimateSize() { return (long) (getFence() - index); }
public int characteristics() { return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; } }
|
#####测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| List<String> arrs=new ArrayList<>(); arrs.add("a"); arrs.add("b"); arrs.add("c"); arrs.add("d"); arrs.add("e"); arrs.add("f"); arrs.add("h"); arrs.add("i"); arrs.add("j"); Spliterator<String> a=arrs.spliterator(); System.out.println(a);
Spliterator<String> b=a.trySplit(); System.out.println(b.toString());
Spliterator<String> c=a.trySplit(); System.out.println(c.toString());
Spliterator<String> d=a.trySplit(); System.out.println(d.toString());
|
可以看到每次分割,都会分割剩余的前一半,fence之不变,index后移。同时也发现:
1.ArrayListSpliterator本质上还是对原list进行操作,只是通过index和fence来控制每次处理范围
2.也可以得出,ArrayListSpliterator在遍历元素时,不能对list进行结构变更操作,否则抛错。
###衍生接口OfPrimitive
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> extends Spliterator<T> { @Override T_SPLITR trySplit();
@SuppressWarnings("overloads") boolean tryAdvance(T_CONS action);
@SuppressWarnings("overloads") default void forEachRemaining(T_CONS action) { do { } while (tryAdvance(action)); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> extends Spliterator<T> { T_SPLITR trySplit();
boolean tryAdvance(T_CONS var1);
default void forEachRemaining(T_CONS var1) { while (this.tryAdvance(var1)) { ; }
} }
|
可以看到,这个接口基本没有变动,这是多增加两个泛型声明而已,本质上和Spliterator没有太大的区别,只不过,它限制tryAdvance的参数action类型T_CONS和trySplit的返回参数T_SPLITR必须在实现接口时先声明类型。
基于OfPrimitive接口,又衍生出了OfInt、OfLong、OfDouble等专门用来处理int、Long、double等分割迭代器接口(在Spliterators有具体的实现)。
LinkedHashSet中的Spliterator方法的实现,内部使用到了Sqlieterator接口的常量值!
##简单的并发测试(jdk1.8+)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| private AtomicInteger count=new AtomicInteger(0); private List<String> strList=createList(); private Spliterator spliterator=strList.spliterator();
@Test public void mytest(){ for(int i=0;i< 4;i++){ new Thread(()->{ String threadName=Thread.currentThread().getName(); System.out.println(" "+threadName+" start "); spliterator.trySplit().forEachRemaining((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+" end"); }).start(); } try{ Thread.sleep(15000); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println("结果为:"+count); }
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("="); } } return result; }
public static boolean isInteger(String str){ Pattern pattern=Pattern.compile("^[-\\+]?[\\d]*$"); return pattern.matcher(str).matches(); }
|
本文地址 Spliterator并行遍历迭代器(JDK8)
本文地址: https://github.com/maxzhao-it/blog/post/42644/