0%

ArrayListSpliterator内部类总结

前言:ArrayListSpliterator是ArrayList的静态内部类,本文将从源码分析与学习ArrayListSpliterator类

ArrayListSpliterator简介

ArrayListSpliterator实现了Spliterator接口,能并行遍历ArrayList集合,特征值为Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED

image-20200102002324367

ArrayListSpliterator源码学习

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
static final class ArrayListSpliterator<E> implements Spliterator<E> {
// 存放ArrayList对象
private final ArrayList<E> list;
// 起始位置(包含)
private int index;
// 结束位置(不包含)
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;
}

// 获取结束位置,用于初始化
private int getFence() {
int hi;
ArrayList<E> lst;
// fence<0时(第一次初始化时,fence才会小于0):
if ((hi = fence) < 0) {
if ((lst = list) == null)
// list为null时,fence=0
hi = fence = 0;
else {
// list不为null时,fence=list的长度
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}

// 分割list,返回一个新分割出的spliterator实例
public ArrayListSpliterator<E> trySplit() {
// hi为结束位置,lo为起始位置,mid为中间值
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
// 当lo>=mid,表示不能在分割,返回null
// 当lo<mid,以mid分割,同时更新index。返回的是list前半部分,当前对象保留后半部分
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处理元素
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) {
// 当fence<0时,进行初始化操作
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() {
// 返回特征值
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}

简单实例

list中存放26个字母,使用ArrayListSpliterator多线程并行遍历

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
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
String letter = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < letter.length(); i++) {
list.add(String.valueOf(letter.charAt(i)));
}
Spliterator<String> spliterator = list.spliterator();
// 估算大小
System.out.println("使用estimateSize()估算大小:" + spliterator.estimateSize());
System.out.println("使用characteristics()获取特征值:" + spliterator.characteristics());

ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i=0;i<4;i++){
executorService.execute(()->{
Spliterator temp = spliterator.trySplit();
temp.forEachRemaining(s -> System.out.println(Thread.currentThread().getName() + "输出list元素" + s));
});
}

// 因为trySplit()是一直对半分,这里处理剩下的数据
executorService.execute(()->{
Spliterator temp = spliterator;
temp.forEachRemaining(s -> System.out.println(Thread.currentThread().getName() + "输出list元素" + s));
});
// 关闭线程池
executorService.shutdown();
}
}

运行结果

image-20200102002350426

-------------本文结束感谢您的阅读-------------