60 |
59 |
61 /** |
60 /** |
62 * An {@code int} range spliterator. |
61 * An {@code int} range spliterator. |
63 */ |
62 */ |
64 static final class RangeIntSpliterator implements Spliterator.OfInt { |
63 static final class RangeIntSpliterator implements Spliterator.OfInt { |
|
64 // Can never be greater that upTo, this avoids overflow if upper bound |
|
65 // is Integer.MAX_VALUE |
|
66 // All elements are traversed if from == upTo & last == 0 |
65 private int from; |
67 private int from; |
66 private final int upTo; |
68 private final int upTo; |
67 private final int step; |
69 // 1 if the range is closed and the last element has not been traversed |
68 |
70 // Otherwise, 0 if the range is open, or is a closed range and all |
69 RangeIntSpliterator(int from, int upTo, int step) { |
71 // elements have been traversed |
|
72 private int last; |
|
73 |
|
74 RangeIntSpliterator(int from, int upTo, boolean closed) { |
|
75 this(from, upTo, closed ? 1 : 0); |
|
76 } |
|
77 |
|
78 private RangeIntSpliterator(int from, int upTo, int last) { |
70 this.from = from; |
79 this.from = from; |
71 this.upTo = upTo; |
80 this.upTo = upTo; |
72 this.step = step; |
81 this.last = last; |
73 } |
82 } |
74 |
83 |
75 @Override |
84 @Override |
76 public boolean tryAdvance(IntConsumer consumer) { |
85 public boolean tryAdvance(IntConsumer consumer) { |
77 boolean hasNext = from < upTo; |
86 final int i = from; |
78 if (hasNext) { |
87 if (i < upTo) { |
79 consumer.accept(from); |
88 from++; |
80 from += step; |
89 consumer.accept(i); |
81 } |
90 return true; |
82 return hasNext; |
91 } |
|
92 else if (last > 0) { |
|
93 last = 0; |
|
94 consumer.accept(i); |
|
95 return true; |
|
96 } |
|
97 return false; |
83 } |
98 } |
84 |
99 |
85 @Override |
100 @Override |
86 public void forEachRemaining(IntConsumer consumer) { |
101 public void forEachRemaining(IntConsumer consumer) { |
87 int hUpTo = upTo; |
102 int i = from; |
88 int hStep = step; // hoist accesses and checks from loop |
103 final int hUpTo = upTo; |
89 for (int i = from; i < hUpTo; i += hStep) |
104 int hLast = last; |
|
105 from = upTo; |
|
106 last = 0; |
|
107 while (i < hUpTo) { |
|
108 consumer.accept(i++); |
|
109 } |
|
110 if (hLast > 0) { |
|
111 // Last element of closed range |
90 consumer.accept(i); |
112 consumer.accept(i); |
91 from = upTo; |
113 } |
92 } |
114 } |
93 |
115 |
94 @Override |
116 @Override |
95 public long estimateSize() { |
117 public long estimateSize() { |
96 int d = upTo - from; |
118 // Ensure ranges of size > Integer.MAX_VALUE report the correct size |
97 return (d / step) + ((d % step == 0) ? 0 : 1); |
119 return ((long) upTo) - from + last; |
98 } |
120 } |
99 |
121 |
100 @Override |
122 @Override |
101 public int characteristics() { |
123 public int characteristics() { |
102 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | |
124 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | |
109 return null; |
131 return null; |
110 } |
132 } |
111 |
133 |
112 @Override |
134 @Override |
113 public Spliterator.OfInt trySplit() { |
135 public Spliterator.OfInt trySplit() { |
114 return estimateSize() <= 1 |
136 long size = estimateSize(); |
|
137 return size <= 1 |
115 ? null |
138 ? null |
116 : new RangeIntSpliterator(from, from = from + midPoint(), step); |
139 // Left split always has a half-open range |
117 } |
140 : new RangeIntSpliterator(from, from = from + splitPoint(size), 0); |
118 |
141 } |
119 private int midPoint() { |
142 |
120 // Size is known to be >= 2 |
143 /** |
121 int bisection = (upTo - from) / 2; |
144 * The spliterator size below which the spliterator will be split |
122 // If bisection > step then round down to nearest multiple of step |
145 * at the mid-point to produce balanced splits. Above this size the |
123 // otherwise round up to step |
146 * spliterator will be split at a ratio of |
124 return bisection > step ? bisection - bisection % step : step; |
147 * 1:(RIGHT_BALANCED_SPLIT_RATIO - 1) |
|
148 * to produce right-balanced splits. |
|
149 * |
|
150 * <p>Such splitting ensures that for very large ranges that the left |
|
151 * side of the range will more likely be processed at a lower-depth |
|
152 * than a balanced tree at the expense of a higher-depth for the right |
|
153 * side of the range. |
|
154 * |
|
155 * <p>This is optimized for cases such as IntStream.ints() that is |
|
156 * implemented as range of 0 to Integer.MAX_VALUE but is likely to be |
|
157 * augmented with a limit operation that limits the number of elements |
|
158 * to a count lower than this threshold. |
|
159 */ |
|
160 private static final int BALANCED_SPLIT_THRESHOLD = 1 << 24; |
|
161 |
|
162 /** |
|
163 * The split ratio of the left and right split when the spliterator |
|
164 * size is above BALANCED_SPLIT_THRESHOLD. |
|
165 */ |
|
166 private static final int RIGHT_BALANCED_SPLIT_RATIO = 1 << 3; |
|
167 |
|
168 private int splitPoint(long size) { |
|
169 int d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO; |
|
170 // 2 <= size <= 2^32 |
|
171 return (int) (size / d); |
125 } |
172 } |
126 } |
173 } |
127 |
174 |
128 /** |
175 /** |
129 * A {@code long} range spliterator. |
176 * A {@code long} range spliterator. |
|
177 * |
|
178 * This implementation cannot be used for ranges whose size is greater |
|
179 * than Long.MAX_VALUE |
130 */ |
180 */ |
131 static final class RangeLongSpliterator implements Spliterator.OfLong { |
181 static final class RangeLongSpliterator implements Spliterator.OfLong { |
|
182 // Can never be greater that upTo, this avoids overflow if upper bound |
|
183 // is Long.MAX_VALUE |
|
184 // All elements are traversed if from == upTo & last == 0 |
132 private long from; |
185 private long from; |
133 private final long upTo; |
186 private final long upTo; |
134 private final long step; |
187 // 1 if the range is closed and the last element has not been traversed |
135 |
188 // Otherwise, 0 if the range is open, or is a closed range and all |
136 RangeLongSpliterator(long from, long upTo, long step) { |
189 // elements have been traversed |
|
190 private int last; |
|
191 |
|
192 RangeLongSpliterator(long from, long upTo, boolean closed) { |
|
193 this(from, upTo, closed ? 1 : 0); |
|
194 } |
|
195 |
|
196 private RangeLongSpliterator(long from, long upTo, int last) { |
|
197 assert upTo - from + last > 0; |
137 this.from = from; |
198 this.from = from; |
138 this.upTo = upTo; |
199 this.upTo = upTo; |
139 this.step = step; |
200 this.last = last; |
140 } |
201 } |
141 |
202 |
142 @Override |
203 @Override |
143 public boolean tryAdvance(LongConsumer consumer) { |
204 public boolean tryAdvance(LongConsumer consumer) { |
144 boolean hasNext = from < upTo; |
205 final long i = from; |
145 if (hasNext) { |
206 if (i < upTo) { |
146 consumer.accept(from); |
207 from++; |
147 from += step; |
208 consumer.accept(i); |
148 } |
209 return true; |
149 return hasNext; |
210 } |
|
211 else if (last > 0) { |
|
212 last = 0; |
|
213 consumer.accept(i); |
|
214 return true; |
|
215 } |
|
216 return false; |
150 } |
217 } |
151 |
218 |
152 @Override |
219 @Override |
153 public void forEachRemaining(LongConsumer consumer) { |
220 public void forEachRemaining(LongConsumer consumer) { |
154 long hUpTo = upTo; |
221 long i = from; |
155 long hStep = step; // hoist accesses and checks from loop |
222 final long hUpTo = upTo; |
156 for (long i = from; i < hUpTo; i += hStep) |
223 int hLast = last; |
|
224 from = upTo; |
|
225 last = 0; |
|
226 while (i < hUpTo) { |
|
227 consumer.accept(i++); |
|
228 } |
|
229 if (hLast > 0) { |
|
230 // Last element of closed range |
157 consumer.accept(i); |
231 consumer.accept(i); |
158 from = upTo; |
232 } |
159 } |
233 } |
160 |
234 |
161 @Override |
235 @Override |
162 public long estimateSize() { |
236 public long estimateSize() { |
163 long d = upTo - from; |
237 return upTo - from + last; |
164 return (d / step) + ((d % step == 0) ? 0 : 1); |
|
165 } |
238 } |
166 |
239 |
167 @Override |
240 @Override |
168 public int characteristics() { |
241 public int characteristics() { |
169 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | |
242 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | |
176 return null; |
249 return null; |
177 } |
250 } |
178 |
251 |
179 @Override |
252 @Override |
180 public Spliterator.OfLong trySplit() { |
253 public Spliterator.OfLong trySplit() { |
181 return estimateSize() <= 1 |
254 long size = estimateSize(); |
|
255 return size <= 1 |
182 ? null |
256 ? null |
183 : new RangeLongSpliterator(from, from = from + midPoint(), step); |
257 // Left split always has a half-open range |
184 } |
258 : new RangeLongSpliterator(from, from = from + splitPoint(size), 0); |
185 |
259 } |
186 private long midPoint() { |
260 |
187 // Size is known to be >= 2 |
261 /** |
188 long bisection = (upTo - from) / 2; |
262 * The spliterator size below which the spliterator will be split |
189 // If bisection > step then round down to nearest multiple of step |
263 * at the mid-point to produce balanced splits. Above this size the |
190 // otherwise round up to step |
264 * spliterator will be split at a ratio of |
191 return bisection > step ? bisection - bisection % step : step; |
265 * 1:(RIGHT_BALANCED_SPLIT_RATIO - 1) |
|
266 * to produce right-balanced splits. |
|
267 * |
|
268 * <p>Such splitting ensures that for very large ranges that the left |
|
269 * side of the range will more likely be processed at a lower-depth |
|
270 * than a balanced tree at the expense of a higher-depth for the right |
|
271 * side of the range. |
|
272 * |
|
273 * <p>This is optimized for cases such as LongStream.longs() that is |
|
274 * implemented as range of 0 to Long.MAX_VALUE but is likely to be |
|
275 * augmented with a limit operation that limits the number of elements |
|
276 * to a count lower than this threshold. |
|
277 */ |
|
278 private static final long BALANCED_SPLIT_THRESHOLD = 1 << 24; |
|
279 |
|
280 /** |
|
281 * The split ratio of the left and right split when the spliterator |
|
282 * size is above BALANCED_SPLIT_THRESHOLD. |
|
283 */ |
|
284 private static final long RIGHT_BALANCED_SPLIT_RATIO = 1 << 3; |
|
285 |
|
286 private long splitPoint(long size) { |
|
287 long d = (size < BALANCED_SPLIT_THRESHOLD) ? 2 : RIGHT_BALANCED_SPLIT_RATIO; |
|
288 // 2 <= size <= Long.MAX_VALUE |
|
289 return size / d; |
192 } |
290 } |
193 } |
291 } |
194 |
292 |
195 private static abstract class AbstractStreamBuilderImpl<T, S extends Spliterator<T>> implements Spliterator<T> { |
293 private static abstract class AbstractStreamBuilderImpl<T, S extends Spliterator<T>> implements Spliterator<T> { |
196 // >= 0 when building, < 0 when built |
294 // >= 0 when building, < 0 when built |