-
Notifications
You must be signed in to change notification settings - Fork 668
/
AbstractSpinedBuffer.java
175 lines (155 loc) · 5.5 KB
/
AbstractSpinedBuffer.java
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util.stream;
/**
* Base class for a data structure for gathering elements into a buffer and then
* iterating them. Maintains an array of increasingly sized arrays, so there is
* no copying cost associated with growing the data structure.
*
* @since 1.8
*/
/*
* 弹性缓冲区的抽象实现
*
* 弹性缓冲区是一个二维数组,该二维数组又由多个一维数组(chunk)组成。
* 当前抽象类主要提供了控制弹性缓冲区中一维数组和二维数组的容量的参数。
*/
abstract class AbstractSpinedBuffer {
/**
* Minimum power-of-two for the first chunk.
*/
/*
* 第一个chunk的初始容量系数
* 比如MIN_CHUNK_POWER = 4,则为第一个chunk分配1<<4的容量
*/
public static final int MIN_CHUNK_POWER = 4;
/**
* Max power-of-two for chunks.
*/
// chunk的最大容量系数
public static final int MAX_CHUNK_POWER = 30;
/**
* Minimum size for the first chunk.
*/
// 第一个chunk的最小容量
public static final int MIN_CHUNK_SIZE = 1 << MIN_CHUNK_POWER;
/**
* Minimum array size for array-of-chunks.
*/
/*
* 弹性缓冲区的最小容量
*
*
*/
public static final int MIN_SPINE_SIZE = 8;
/**
* log2 of the size of the first chunk.
*/
/*
* 新建一个chunk时使用的容量系数
*
* 初始时,该系数等于MIN_CHUNK_POWER,后续会增大。
*/
protected final int initialChunkPower;
/**
* Index of the *next* element to write; may point into, or just outside of, the current chunk.
*/
// 追踪当前chunk中的元素的索引,用来指示当前的一维缓存是否已满
protected int elementIndex;
/**
* Index of the *current* chunk in the spine array, if the spine array is non-null.
*/
// 二维缓存的行索引,指向当前chunk
protected int spineIndex;
/**
* Count of elements in all prior chunks.
*/
/*
* 记录当前chunk之前已经存储了多少个元素
*
* 比如priorElementCount[0]总是等于0,代表二维缓冲区索引为0的chunk之前没有元素;
* priorElementCount[1]=n代表二维缓冲区索引为1的chunk之前已经存储了n个元素。
*
* 设置此变量的必要性在于二维缓冲区是一个参差数组,即二维缓冲区的每一行包含的元素并不相等。
*/
protected long[] priorElementCount;
/**
* Construct with an initial capacity of 16.
*/
protected AbstractSpinedBuffer() {
this.initialChunkPower = MIN_CHUNK_POWER;
}
/**
* Construct with a specified initial capacity.
*
* @param initialCapacity The minimum expected number of elements
*/
protected AbstractSpinedBuffer(int initialCapacity) {
if(initialCapacity<0) {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
/*
* Integer.numberOfLeadingZeros()
* 返回整数i的二进制位左边连续的0的个数,范围在0~32
* 这里,initialChunkPower范围也在0~32
*/
this.initialChunkPower = Math.max(MIN_CHUNK_POWER, Integer.SIZE - Integer.numberOfLeadingZeros(initialCapacity - 1));
}
/**
* Is the buffer currently empty?
*/
// 判断弹性缓冲区中是否为空
public boolean isEmpty() {
return (spineIndex == 0) && (elementIndex == 0);
}
/**
* How many elements are currently in the buffer?
*/
// 返回弹性缓冲区中所有元素数量
public long count() {
if(spineIndex == 0) {
return elementIndex;
}
return priorElementCount[spineIndex] + elementIndex;
}
/**
* Remove all data from the buffer
*/
// 清空弹性缓冲区
public abstract void clear();
/**
* How big should the nth chunk be?
*/
// 返回下一个新建chunk的容量
protected int chunkSize(int n) {
int power;
if(n == 0 || n == 1) {
power = initialChunkPower;
} else {
power = Math.min(initialChunkPower + n - 1, AbstractSpinedBuffer.MAX_CHUNK_POWER);
}
return 1 << power;
}
}