提交 345ff4eb 编写于 作者: P psandoz

8016251: Balanced spliterator for SpinedBuffer

Reviewed-by: mduigou
Contributed-by: NBrian Goetz &lt;brian.goetz@oracle.com&gt;, Peter Levart &lt;peter.levart@gmail.com&gt;, Paul Sandoz <paul.sandoz@oracle.com>
上级 47266178
...@@ -461,7 +461,7 @@ abstract class DoublePipeline<E_IN> ...@@ -461,7 +461,7 @@ abstract class DoublePipeline<E_IN>
@Override @Override
public final double[] toArray() { public final double[] toArray() {
return Nodes.flattenDouble((Node.OfDouble) evaluateToArrayNode(Double[]::new)) return Nodes.flattenDouble((Node.OfDouble) evaluateToArrayNode(Double[]::new))
.asDoubleArray(); .asPrimitiveArray();
} }
// //
......
...@@ -498,7 +498,7 @@ abstract class IntPipeline<E_IN> ...@@ -498,7 +498,7 @@ abstract class IntPipeline<E_IN>
@Override @Override
public final int[] toArray() { public final int[] toArray() {
return Nodes.flattenInt((Node.OfInt) evaluateToArrayNode(Integer[]::new)) return Nodes.flattenInt((Node.OfInt) evaluateToArrayNode(Integer[]::new))
.asIntArray(); .asPrimitiveArray();
} }
// //
......
...@@ -479,7 +479,8 @@ abstract class LongPipeline<E_IN> ...@@ -479,7 +479,8 @@ abstract class LongPipeline<E_IN>
@Override @Override
public final long[] toArray() { public final long[] toArray() {
return Nodes.flattenLong((Node.OfLong) evaluateToArrayNode(Long[]::new)).asLongArray(); return Nodes.flattenLong((Node.OfLong) evaluateToArrayNode(Long[]::new))
.asPrimitiveArray();
} }
......
...@@ -242,7 +242,7 @@ interface Node<T> { ...@@ -242,7 +242,7 @@ interface Node<T> {
* an instance of an Integer[] array with a length of {@link #count()} * an instance of an Integer[] array with a length of {@link #count()}
* and then invokes {@link #copyInto(Integer[], int)} with that * and then invokes {@link #copyInto(Integer[], int)} with that
* Integer[] array at an offset of 0. This is not efficient and it is * Integer[] array at an offset of 0. This is not efficient and it is
* recommended to invoke {@link #asIntArray()}. * recommended to invoke {@link #asPrimitiveArray()}.
*/ */
@Override @Override
default Integer[] asArray(IntFunction<Integer[]> generator) { default Integer[] asArray(IntFunction<Integer[]> generator) {
...@@ -254,7 +254,7 @@ interface Node<T> { ...@@ -254,7 +254,7 @@ interface Node<T> {
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* @implSpec the default implementation invokes {@link #asIntArray()} to * @implSpec the default implementation invokes {@link #asPrimitiveArray()} to
* obtain an int[] array then and copies the elements from that int[] * obtain an int[] array then and copies the elements from that int[]
* array into the boxed Integer[] array. This is not efficient and it * array into the boxed Integer[] array. This is not efficient and it
* is recommended to invoke {@link #copyInto(int[], int)}. * is recommended to invoke {@link #copyInto(int[], int)}.
...@@ -264,7 +264,7 @@ interface Node<T> { ...@@ -264,7 +264,7 @@ interface Node<T> {
if (Tripwire.ENABLED) if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling Node.OfInt.copyInto(Integer[], int)"); Tripwire.trip(getClass(), "{0} calling Node.OfInt.copyInto(Integer[], int)");
int[] array = asIntArray(); int[] array = asPrimitiveArray();
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
boxed[offset + i] = array[i]; boxed[offset + i] = array[i];
} }
...@@ -285,7 +285,7 @@ interface Node<T> { ...@@ -285,7 +285,7 @@ interface Node<T> {
* *
* @return an array containing the contents of this {@code Node} * @return an array containing the contents of this {@code Node}
*/ */
int[] asIntArray(); int[] asPrimitiveArray();
/** /**
* Copies the content of this {@code Node} into an int[] array, starting * Copies the content of this {@code Node} into an int[] array, starting
...@@ -362,7 +362,7 @@ interface Node<T> { ...@@ -362,7 +362,7 @@ interface Node<T> {
* an instance of a Long[] array with a length of {@link #count()} and * an instance of a Long[] array with a length of {@link #count()} and
* then invokes {@link #copyInto(Long[], int)} with that Long[] array at * then invokes {@link #copyInto(Long[], int)} with that Long[] array at
* an offset of 0. This is not efficient and it is recommended to * an offset of 0. This is not efficient and it is recommended to
* invoke {@link #asLongArray()}. * invoke {@link #asPrimitiveArray()}.
*/ */
@Override @Override
default Long[] asArray(IntFunction<Long[]> generator) { default Long[] asArray(IntFunction<Long[]> generator) {
...@@ -374,7 +374,7 @@ interface Node<T> { ...@@ -374,7 +374,7 @@ interface Node<T> {
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* @implSpec the default implementation invokes {@link #asLongArray()} * @implSpec the default implementation invokes {@link #asPrimitiveArray()}
* to obtain a long[] array then and copies the elements from that * to obtain a long[] array then and copies the elements from that
* long[] array into the boxed Long[] array. This is not efficient and * long[] array into the boxed Long[] array. This is not efficient and
* it is recommended to invoke {@link #copyInto(long[], int)}. * it is recommended to invoke {@link #copyInto(long[], int)}.
...@@ -384,7 +384,7 @@ interface Node<T> { ...@@ -384,7 +384,7 @@ interface Node<T> {
if (Tripwire.ENABLED) if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling Node.OfInt.copyInto(Long[], int)"); Tripwire.trip(getClass(), "{0} calling Node.OfInt.copyInto(Long[], int)");
long[] array = asLongArray(); long[] array = asPrimitiveArray();
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
boxed[offset + i] = array[i]; boxed[offset + i] = array[i];
} }
...@@ -405,7 +405,7 @@ interface Node<T> { ...@@ -405,7 +405,7 @@ interface Node<T> {
* *
* @return an array containing the contents of this {@code Node} * @return an array containing the contents of this {@code Node}
*/ */
long[] asLongArray(); long[] asPrimitiveArray();
/** /**
* Copies the content of this {@code Node} into a long[] array, starting * Copies the content of this {@code Node} into a long[] array, starting
...@@ -485,7 +485,7 @@ interface Node<T> { ...@@ -485,7 +485,7 @@ interface Node<T> {
* an instance of a Double[] array with a length of {@link #count()} and * an instance of a Double[] array with a length of {@link #count()} and
* then invokes {@link #copyInto(Double[], int)} with that Double[] * then invokes {@link #copyInto(Double[], int)} with that Double[]
* array at an offset of 0. This is not efficient and it is recommended * array at an offset of 0. This is not efficient and it is recommended
* to invoke {@link #asDoubleArray()}. * to invoke {@link #asPrimitiveArray()}.
*/ */
@Override @Override
default Double[] asArray(IntFunction<Double[]> generator) { default Double[] asArray(IntFunction<Double[]> generator) {
...@@ -497,7 +497,7 @@ interface Node<T> { ...@@ -497,7 +497,7 @@ interface Node<T> {
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* @implSpec the default implementation invokes {@link #asDoubleArray()} * @implSpec the default implementation invokes {@link #asPrimitiveArray()}
* to obtain a double[] array then and copies the elements from that * to obtain a double[] array then and copies the elements from that
* double[] array into the boxed Double[] array. This is not efficient * double[] array into the boxed Double[] array. This is not efficient
* and it is recommended to invoke {@link #copyInto(double[], int)}. * and it is recommended to invoke {@link #copyInto(double[], int)}.
...@@ -507,7 +507,7 @@ interface Node<T> { ...@@ -507,7 +507,7 @@ interface Node<T> {
if (Tripwire.ENABLED) if (Tripwire.ENABLED)
Tripwire.trip(getClass(), "{0} calling Node.OfDouble.copyInto(Double[], int)"); Tripwire.trip(getClass(), "{0} calling Node.OfDouble.copyInto(Double[], int)");
double[] array = asDoubleArray(); double[] array = asPrimitiveArray();
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
boxed[offset + i] = array[i]; boxed[offset + i] = array[i];
} }
...@@ -528,7 +528,7 @@ interface Node<T> { ...@@ -528,7 +528,7 @@ interface Node<T> {
* *
* @return an array containing the contents of this {@code Node} * @return an array containing the contents of this {@code Node}
*/ */
double[] asDoubleArray(); double[] asPrimitiveArray();
/** /**
* Copies the content of this {@code Node} into a double[] array, starting * Copies the content of this {@code Node} into a double[] array, starting
......
...@@ -679,7 +679,7 @@ final class Nodes { ...@@ -679,7 +679,7 @@ final class Nodes {
} }
@Override @Override
public int[] asIntArray() { public int[] asPrimitiveArray() {
return EMPTY_INT_ARRAY; return EMPTY_INT_ARRAY;
} }
} }
...@@ -696,7 +696,7 @@ final class Nodes { ...@@ -696,7 +696,7 @@ final class Nodes {
} }
@Override @Override
public long[] asLongArray() { public long[] asPrimitiveArray() {
return EMPTY_LONG_ARRAY; return EMPTY_LONG_ARRAY;
} }
} }
...@@ -713,7 +713,7 @@ final class Nodes { ...@@ -713,7 +713,7 @@ final class Nodes {
} }
@Override @Override
public double[] asDoubleArray() { public double[] asPrimitiveArray() {
return EMPTY_DOUBLE_ARRAY; return EMPTY_DOUBLE_ARRAY;
} }
} }
...@@ -1395,7 +1395,7 @@ final class Nodes { ...@@ -1395,7 +1395,7 @@ final class Nodes {
} }
@Override @Override
public int[] asIntArray() { public int[] asPrimitiveArray() {
if (array.length == curSize) { if (array.length == curSize) {
return array; return array;
} else { } else {
...@@ -1449,7 +1449,7 @@ final class Nodes { ...@@ -1449,7 +1449,7 @@ final class Nodes {
} }
@Override @Override
public long[] asLongArray() { public long[] asPrimitiveArray() {
if (array.length == curSize) { if (array.length == curSize) {
return array; return array;
} else { } else {
...@@ -1503,7 +1503,7 @@ final class Nodes { ...@@ -1503,7 +1503,7 @@ final class Nodes {
} }
@Override @Override
public double[] asDoubleArray() { public double[] asPrimitiveArray() {
if (array.length == curSize) { if (array.length == curSize) {
return array; return array;
} else { } else {
...@@ -1561,7 +1561,7 @@ final class Nodes { ...@@ -1561,7 +1561,7 @@ final class Nodes {
} }
@Override @Override
public int[] asIntArray() { public int[] asPrimitiveArray() {
int[] array = new int[(int) count()]; int[] array = new int[(int) count()];
copyInto(array, 0); copyInto(array, 0);
return array; return array;
...@@ -1594,7 +1594,7 @@ final class Nodes { ...@@ -1594,7 +1594,7 @@ final class Nodes {
} }
@Override @Override
public long[] asLongArray() { public long[] asPrimitiveArray() {
long[] array = new long[(int) count()]; long[] array = new long[(int) count()];
copyInto(array, 0); copyInto(array, 0);
return array; return array;
...@@ -1627,7 +1627,7 @@ final class Nodes { ...@@ -1627,7 +1627,7 @@ final class Nodes {
} }
@Override @Override
public double[] asDoubleArray() { public double[] asPrimitiveArray() {
double[] array = new double[(int) count()]; double[] array = new double[(int) count()];
copyInto(array, 0); copyInto(array, 0);
return array; return array;
...@@ -1844,9 +1844,9 @@ final class Nodes { ...@@ -1844,9 +1844,9 @@ final class Nodes {
} }
@Override @Override
public int[] asIntArray() { public int[] asPrimitiveArray() {
assert !building : "during building"; assert !building : "during building";
return super.asIntArray(); return super.asPrimitiveArray();
} }
@Override @Override
...@@ -1904,9 +1904,9 @@ final class Nodes { ...@@ -1904,9 +1904,9 @@ final class Nodes {
} }
@Override @Override
public long[] asLongArray() { public long[] asPrimitiveArray() {
assert !building : "during building"; assert !building : "during building";
return super.asLongArray(); return super.asPrimitiveArray();
} }
@Override @Override
...@@ -1964,9 +1964,9 @@ final class Nodes { ...@@ -1964,9 +1964,9 @@ final class Nodes {
} }
@Override @Override
public double[] asDoubleArray() { public double[] asPrimitiveArray() {
assert !building : "during building"; assert !building : "during building";
return super.asDoubleArray(); return super.asPrimitiveArray();
} }
@Override @Override
......
...@@ -192,7 +192,7 @@ final class SortedOps { ...@@ -192,7 +192,7 @@ final class SortedOps {
else { else {
Node.OfInt n = (Node.OfInt) helper.evaluate(spliterator, true, generator); Node.OfInt n = (Node.OfInt) helper.evaluate(spliterator, true, generator);
int[] content = n.asIntArray(); int[] content = n.asPrimitiveArray();
Arrays.parallelSort(content); Arrays.parallelSort(content);
return Nodes.node(content); return Nodes.node(content);
...@@ -231,7 +231,7 @@ final class SortedOps { ...@@ -231,7 +231,7 @@ final class SortedOps {
else { else {
Node.OfLong n = (Node.OfLong) helper.evaluate(spliterator, true, generator); Node.OfLong n = (Node.OfLong) helper.evaluate(spliterator, true, generator);
long[] content = n.asLongArray(); long[] content = n.asPrimitiveArray();
Arrays.parallelSort(content); Arrays.parallelSort(content);
return Nodes.node(content); return Nodes.node(content);
...@@ -270,7 +270,7 @@ final class SortedOps { ...@@ -270,7 +270,7 @@ final class SortedOps {
else { else {
Node.OfDouble n = (Node.OfDouble) helper.evaluate(spliterator, true, generator); Node.OfDouble n = (Node.OfDouble) helper.evaluate(spliterator, true, generator);
double[] content = n.asDoubleArray(); double[] content = n.asPrimitiveArray();
Arrays.parallelSort(content); Arrays.parallelSort(content);
return Nodes.node(content); return Nodes.node(content);
...@@ -401,7 +401,7 @@ final class SortedOps { ...@@ -401,7 +401,7 @@ final class SortedOps {
@Override @Override
public void end() { public void end() {
int[] ints = b.asIntArray(); int[] ints = b.asPrimitiveArray();
Arrays.sort(ints); Arrays.sort(ints);
downstream.begin(ints.length); downstream.begin(ints.length);
for (int anInt : ints) for (int anInt : ints)
...@@ -466,7 +466,7 @@ final class SortedOps { ...@@ -466,7 +466,7 @@ final class SortedOps {
@Override @Override
public void end() { public void end() {
long[] longs = b.asLongArray(); long[] longs = b.asPrimitiveArray();
Arrays.sort(longs); Arrays.sort(longs);
downstream.begin(longs.length); downstream.begin(longs.length);
for (long aLong : longs) for (long aLong : longs)
...@@ -531,7 +531,7 @@ final class SortedOps { ...@@ -531,7 +531,7 @@ final class SortedOps {
@Override @Override
public void end() { public void end() {
double[] doubles = b.asDoubleArray(); double[] doubles = b.asPrimitiveArray();
Arrays.sort(doubles); Arrays.sort(doubles);
downstream.begin(doubles.length); downstream.begin(doubles.length);
for (double aDouble : doubles) for (double aDouble : doubles)
......
...@@ -269,25 +269,45 @@ class SpinedBuffer<E> ...@@ -269,25 +269,45 @@ class SpinedBuffer<E>
* Return a {@link Spliterator} describing the contents of the buffer. * Return a {@link Spliterator} describing the contents of the buffer.
*/ */
public Spliterator<E> spliterator() { public Spliterator<E> spliterator() {
return new Spliterator<E>() { class Splitr implements Spliterator<E> {
// The current spine index // The current spine index
int splSpineIndex; int splSpineIndex;
// Last spine index
final int lastSpineIndex;
// The current element index into the current spine // The current element index into the current spine
int splElementIndex; int splElementIndex;
// When splSpineIndex >= spineIndex and splElementIndex >= elementIndex then // Last spine's last element index + 1
final int lastSpineElementFence;
// When splSpineIndex >= lastSpineIndex and
// splElementIndex >= lastSpineElementFence then
// this spliterator is fully traversed // this spliterator is fully traversed
// tryAdvance can set splSpineIndex > spineIndex if the last spine is full // tryAdvance can set splSpineIndex > spineIndex if the last spine is full
// The current spine array // The current spine array
E[] splChunk = (spine == null) ? curChunk : spine[0]; E[] splChunk;
Splitr(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
this.splSpineIndex = firstSpineIndex;
this.lastSpineIndex = lastSpineIndex;
this.splElementIndex = firstSpineElementIndex;
this.lastSpineElementFence = lastSpineElementFence;
assert spine != null || firstSpineIndex == 0 && lastSpineIndex == 0;
splChunk = (spine == null) ? curChunk : spine[firstSpineIndex];
}
@Override @Override
public long estimateSize() { public long estimateSize() {
return (spine == null) return (splSpineIndex == lastSpineIndex)
? (elementIndex - splElementIndex) ? (long) lastSpineElementFence - splElementIndex
: count() - (priorElementCount[splSpineIndex] + splElementIndex); : // # of elements prior to end -
priorElementCount[lastSpineIndex] + lastSpineElementFence -
// # of elements prior to current
priorElementCount[splSpineIndex] - splElementIndex;
} }
@Override @Override
...@@ -297,14 +317,14 @@ class SpinedBuffer<E> ...@@ -297,14 +317,14 @@ class SpinedBuffer<E>
@Override @Override
public boolean tryAdvance(Consumer<? super E> consumer) { public boolean tryAdvance(Consumer<? super E> consumer) {
if (splSpineIndex < spineIndex if (splSpineIndex < lastSpineIndex
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) { || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
consumer.accept(splChunk[splElementIndex++]); consumer.accept(splChunk[splElementIndex++]);
if (splElementIndex == splChunk.length) { if (splElementIndex == splChunk.length) {
splElementIndex = 0; splElementIndex = 0;
++splSpineIndex; ++splSpineIndex;
if (spine != null && splSpineIndex < spine.length) if (spine != null && splSpineIndex <= lastSpineIndex)
splChunk = spine[splSpineIndex]; splChunk = spine[splSpineIndex];
} }
return true; return true;
...@@ -314,45 +334,47 @@ class SpinedBuffer<E> ...@@ -314,45 +334,47 @@ class SpinedBuffer<E>
@Override @Override
public void forEachRemaining(Consumer<? super E> consumer) { public void forEachRemaining(Consumer<? super E> consumer) {
if (splSpineIndex < spineIndex if (splSpineIndex < lastSpineIndex
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) { || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
int i = splElementIndex; int i = splElementIndex;
// completed chunks, if any // completed chunks, if any
for (int sp = splSpineIndex; sp < spineIndex; sp++) { for (int sp = splSpineIndex; sp < lastSpineIndex; sp++) {
E[] chunk = spine[sp]; E[] chunk = spine[sp];
for (; i < chunk.length; i++) { for (; i < chunk.length; i++) {
consumer.accept(chunk[i]); consumer.accept(chunk[i]);
} }
i = 0; i = 0;
} }
// last (or current uncompleted) chunk
// current chunk E[] chunk = (splSpineIndex == lastSpineIndex) ? splChunk : spine[lastSpineIndex];
E[] chunk = curChunk; int hElementIndex = lastSpineElementFence;
int hElementIndex = elementIndex;
for (; i < hElementIndex; i++) { for (; i < hElementIndex; i++) {
consumer.accept(chunk[i]); consumer.accept(chunk[i]);
} }
// mark consumed
splSpineIndex = spineIndex; splSpineIndex = lastSpineIndex;
splElementIndex = elementIndex; splElementIndex = lastSpineElementFence;
} }
} }
@Override @Override
public Spliterator<E> trySplit() { public Spliterator<E> trySplit() {
if (splSpineIndex < spineIndex) { if (splSpineIndex < lastSpineIndex) {
Spliterator<E> ret = Arrays.spliterator(spine[splSpineIndex], // split just before last chunk (if it is full this means 50:50 split)
splElementIndex, spine[splSpineIndex].length); Spliterator<E> ret = new Splitr(splSpineIndex, lastSpineIndex - 1,
splChunk = spine[++splSpineIndex]; splElementIndex, spine[lastSpineIndex-1].length);
// position to start of last chunk
splSpineIndex = lastSpineIndex;
splElementIndex = 0; splElementIndex = 0;
splChunk = spine[splSpineIndex];
return ret; return ret;
} }
else if (splSpineIndex == spineIndex) { else if (splSpineIndex == lastSpineIndex) {
int t = (elementIndex - splElementIndex) / 2; int t = (lastSpineElementFence - splElementIndex) / 2;
if (t == 0) if (t == 0)
return null; return null;
else { else {
Spliterator<E> ret = Arrays.spliterator(curChunk, splElementIndex, splElementIndex + t); Spliterator<E> ret = Arrays.spliterator(splChunk, splElementIndex, splElementIndex + t);
splElementIndex += t; splElementIndex += t;
return ret; return ret;
} }
...@@ -361,7 +383,8 @@ class SpinedBuffer<E> ...@@ -361,7 +383,8 @@ class SpinedBuffer<E>
return null; return null;
} }
} }
}; }
return new Splitr(0, spineIndex, 0, elementIndex);
} }
/** /**
...@@ -436,7 +459,7 @@ class SpinedBuffer<E> ...@@ -436,7 +459,7 @@ class SpinedBuffer<E>
protected abstract T_ARR[] newArrayArray(int size); protected abstract T_ARR[] newArrayArray(int size);
/** Create a new array of the proper type and size */ /** Create a new array of the proper type and size */
protected abstract T_ARR newArray(int size); public abstract T_ARR newArray(int size);
/** Get the length of an array */ /** Get the length of an array */
protected abstract int arrayLength(T_ARR array); protected abstract int arrayLength(T_ARR array);
...@@ -555,30 +578,53 @@ class SpinedBuffer<E> ...@@ -555,30 +578,53 @@ class SpinedBuffer<E>
arrayForEach(curChunk, 0, elementIndex, consumer); arrayForEach(curChunk, 0, elementIndex, consumer);
} }
abstract class BaseSpliterator<T_SPLITER extends Spliterator<E>> abstract class BaseSpliterator<T_SPLITR extends Spliterator.OfPrimitive<E, T_CONS, T_SPLITR>>
implements Spliterator<E> { implements Spliterator.OfPrimitive<E, T_CONS, T_SPLITR> {
// The current spine index // The current spine index
int splSpineIndex; int splSpineIndex;
// Last spine index
final int lastSpineIndex;
// The current element index into the current spine // The current element index into the current spine
int splElementIndex; int splElementIndex;
// When splSpineIndex >= spineIndex and splElementIndex >= elementIndex then // Last spine's last element index + 1
final int lastSpineElementFence;
// When splSpineIndex >= lastSpineIndex and
// splElementIndex >= lastSpineElementFence then
// this spliterator is fully traversed // this spliterator is fully traversed
// tryAdvance can set splSpineIndex > spineIndex if the last spine is full // tryAdvance can set splSpineIndex > spineIndex if the last spine is full
// The current spine array // The current spine array
T_ARR splChunk = (spine == null) ? curChunk : spine[0]; T_ARR splChunk;
BaseSpliterator(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
this.splSpineIndex = firstSpineIndex;
this.lastSpineIndex = lastSpineIndex;
this.splElementIndex = firstSpineElementIndex;
this.lastSpineElementFence = lastSpineElementFence;
assert spine != null || firstSpineIndex == 0 && lastSpineIndex == 0;
splChunk = (spine == null) ? curChunk : spine[firstSpineIndex];
}
abstract T_SPLITR newSpliterator(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence);
abstract void arrayForOne(T_ARR array, int index, T_CONS consumer); abstract void arrayForOne(T_ARR array, int index, T_CONS consumer);
abstract T_SPLITER arraySpliterator(T_ARR array, int offset, int len); abstract T_SPLITR arraySpliterator(T_ARR array, int offset, int len);
@Override @Override
public long estimateSize() { public long estimateSize() {
return (spine == null) return (splSpineIndex == lastSpineIndex)
? (elementIndex - splElementIndex) ? (long) lastSpineElementFence - splElementIndex
: count() - (priorElementCount[splSpineIndex] + splElementIndex); : // # of elements prior to end -
priorElementCount[lastSpineIndex] + lastSpineElementFence -
// # of elements prior to current
priorElementCount[splSpineIndex] - splElementIndex;
} }
@Override @Override
...@@ -586,15 +632,16 @@ class SpinedBuffer<E> ...@@ -586,15 +632,16 @@ class SpinedBuffer<E>
return SPLITERATOR_CHARACTERISTICS; return SPLITERATOR_CHARACTERISTICS;
} }
@Override
public boolean tryAdvance(T_CONS consumer) { public boolean tryAdvance(T_CONS consumer) {
if (splSpineIndex < spineIndex if (splSpineIndex < lastSpineIndex
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) { || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
arrayForOne(splChunk, splElementIndex++, consumer); arrayForOne(splChunk, splElementIndex++, consumer);
if (splElementIndex == arrayLength(splChunk)) { if (splElementIndex == arrayLength(splChunk)) {
splElementIndex = 0; splElementIndex = 0;
++splSpineIndex; ++splSpineIndex;
if (spine != null && splSpineIndex < spine.length) if (spine != null && splSpineIndex <= lastSpineIndex)
splChunk = spine[splSpineIndex]; splChunk = spine[splSpineIndex];
} }
return true; return true;
...@@ -602,39 +649,44 @@ class SpinedBuffer<E> ...@@ -602,39 +649,44 @@ class SpinedBuffer<E>
return false; return false;
} }
@Override
public void forEachRemaining(T_CONS consumer) { public void forEachRemaining(T_CONS consumer) {
if (splSpineIndex < spineIndex if (splSpineIndex < lastSpineIndex
|| (splSpineIndex == spineIndex && splElementIndex < elementIndex)) { || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) {
int i = splElementIndex; int i = splElementIndex;
// completed chunks, if any // completed chunks, if any
for (int sp = splSpineIndex; sp < spineIndex; sp++) { for (int sp = splSpineIndex; sp < lastSpineIndex; sp++) {
T_ARR chunk = spine[sp]; T_ARR chunk = spine[sp];
arrayForEach(chunk, i, arrayLength(chunk), consumer); arrayForEach(chunk, i, arrayLength(chunk), consumer);
i = 0; i = 0;
} }
// last (or current uncompleted) chunk
arrayForEach(curChunk, i, elementIndex, consumer); T_ARR chunk = (splSpineIndex == lastSpineIndex) ? splChunk : spine[lastSpineIndex];
arrayForEach(chunk, i, lastSpineElementFence, consumer);
splSpineIndex = spineIndex; // mark consumed
splElementIndex = elementIndex; splSpineIndex = lastSpineIndex;
splElementIndex = lastSpineElementFence;
} }
} }
@Override @Override
public T_SPLITER trySplit() { public T_SPLITR trySplit() {
if (splSpineIndex < spineIndex) { if (splSpineIndex < lastSpineIndex) {
T_SPLITER ret = arraySpliterator(spine[splSpineIndex], splElementIndex, // split just before last chunk (if it is full this means 50:50 split)
arrayLength(spine[splSpineIndex]) - splElementIndex); T_SPLITR ret = newSpliterator(splSpineIndex, lastSpineIndex - 1,
splChunk = spine[++splSpineIndex]; splElementIndex, arrayLength(spine[lastSpineIndex - 1]));
// position us to start of last chunk
splSpineIndex = lastSpineIndex;
splElementIndex = 0; splElementIndex = 0;
splChunk = spine[splSpineIndex];
return ret; return ret;
} }
else if (splSpineIndex == spineIndex) { else if (splSpineIndex == lastSpineIndex) {
int t = (elementIndex - splElementIndex) / 2; int t = (lastSpineElementFence - splElementIndex) / 2;
if (t == 0) if (t == 0)
return null; return null;
else { else {
T_SPLITER ret = arraySpliterator(curChunk, splElementIndex, t); T_SPLITR ret = arraySpliterator(splChunk, splElementIndex, t);
splElementIndex += t; splElementIndex += t;
return ret; return ret;
} }
...@@ -675,7 +727,7 @@ class SpinedBuffer<E> ...@@ -675,7 +727,7 @@ class SpinedBuffer<E>
} }
@Override @Override
protected int[] newArray(int size) { public int[] newArray(int size) {
return new int[size]; return new int[size];
} }
...@@ -706,10 +758,6 @@ class SpinedBuffer<E> ...@@ -706,10 +758,6 @@ class SpinedBuffer<E>
return spine[ch][(int) (index-priorElementCount[ch])]; return spine[ch][(int) (index-priorElementCount[ch])];
} }
public int[] asIntArray() {
return asPrimitiveArray();
}
@Override @Override
public PrimitiveIterator.OfInt iterator() { public PrimitiveIterator.OfInt iterator() {
return Spliterators.iterator(spliterator()); return Spliterators.iterator(spliterator());
...@@ -718,6 +766,18 @@ class SpinedBuffer<E> ...@@ -718,6 +766,18 @@ class SpinedBuffer<E>
public Spliterator.OfInt spliterator() { public Spliterator.OfInt spliterator() {
class Splitr extends BaseSpliterator<Spliterator.OfInt> class Splitr extends BaseSpliterator<Spliterator.OfInt>
implements Spliterator.OfInt { implements Spliterator.OfInt {
Splitr(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
super(firstSpineIndex, lastSpineIndex,
firstSpineElementIndex, lastSpineElementFence);
}
@Override
Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
return new Splitr(firstSpineIndex, lastSpineIndex,
firstSpineElementIndex, lastSpineElementFence);
}
@Override @Override
void arrayForOne(int[] array, int index, IntConsumer consumer) { void arrayForOne(int[] array, int index, IntConsumer consumer) {
...@@ -728,13 +788,13 @@ class SpinedBuffer<E> ...@@ -728,13 +788,13 @@ class SpinedBuffer<E>
Spliterator.OfInt arraySpliterator(int[] array, int offset, int len) { Spliterator.OfInt arraySpliterator(int[] array, int offset, int len) {
return Arrays.spliterator(array, offset, offset+len); return Arrays.spliterator(array, offset, offset+len);
} }
}; }
return new Splitr(); return new Splitr(0, spineIndex, 0, elementIndex);
} }
@Override @Override
public String toString() { public String toString() {
int[] array = asIntArray(); int[] array = asPrimitiveArray();
if (array.length < 200) { if (array.length < 200) {
return String.format("%s[length=%d, chunks=%d]%s", return String.format("%s[length=%d, chunks=%d]%s",
getClass().getSimpleName(), array.length, getClass().getSimpleName(), array.length,
...@@ -778,7 +838,7 @@ class SpinedBuffer<E> ...@@ -778,7 +838,7 @@ class SpinedBuffer<E>
} }
@Override @Override
protected long[] newArray(int size) { public long[] newArray(int size) {
return new long[size]; return new long[size];
} }
...@@ -809,10 +869,6 @@ class SpinedBuffer<E> ...@@ -809,10 +869,6 @@ class SpinedBuffer<E>
return spine[ch][(int) (index-priorElementCount[ch])]; return spine[ch][(int) (index-priorElementCount[ch])];
} }
public long[] asLongArray() {
return asPrimitiveArray();
}
@Override @Override
public PrimitiveIterator.OfLong iterator() { public PrimitiveIterator.OfLong iterator() {
return Spliterators.iterator(spliterator()); return Spliterators.iterator(spliterator());
...@@ -822,6 +878,19 @@ class SpinedBuffer<E> ...@@ -822,6 +878,19 @@ class SpinedBuffer<E>
public Spliterator.OfLong spliterator() { public Spliterator.OfLong spliterator() {
class Splitr extends BaseSpliterator<Spliterator.OfLong> class Splitr extends BaseSpliterator<Spliterator.OfLong>
implements Spliterator.OfLong { implements Spliterator.OfLong {
Splitr(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
super(firstSpineIndex, lastSpineIndex,
firstSpineElementIndex, lastSpineElementFence);
}
@Override
Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
return new Splitr(firstSpineIndex, lastSpineIndex,
firstSpineElementIndex, lastSpineElementFence);
}
@Override @Override
void arrayForOne(long[] array, int index, LongConsumer consumer) { void arrayForOne(long[] array, int index, LongConsumer consumer) {
consumer.accept(array[index]); consumer.accept(array[index]);
...@@ -831,13 +900,13 @@ class SpinedBuffer<E> ...@@ -831,13 +900,13 @@ class SpinedBuffer<E>
Spliterator.OfLong arraySpliterator(long[] array, int offset, int len) { Spliterator.OfLong arraySpliterator(long[] array, int offset, int len) {
return Arrays.spliterator(array, offset, offset+len); return Arrays.spliterator(array, offset, offset+len);
} }
}; }
return new Splitr(); return new Splitr(0, spineIndex, 0, elementIndex);
} }
@Override @Override
public String toString() { public String toString() {
long[] array = asLongArray(); long[] array = asPrimitiveArray();
if (array.length < 200) { if (array.length < 200) {
return String.format("%s[length=%d, chunks=%d]%s", return String.format("%s[length=%d, chunks=%d]%s",
getClass().getSimpleName(), array.length, getClass().getSimpleName(), array.length,
...@@ -882,7 +951,7 @@ class SpinedBuffer<E> ...@@ -882,7 +951,7 @@ class SpinedBuffer<E>
} }
@Override @Override
protected double[] newArray(int size) { public double[] newArray(int size) {
return new double[size]; return new double[size];
} }
...@@ -913,10 +982,6 @@ class SpinedBuffer<E> ...@@ -913,10 +982,6 @@ class SpinedBuffer<E>
return spine[ch][(int) (index-priorElementCount[ch])]; return spine[ch][(int) (index-priorElementCount[ch])];
} }
public double[] asDoubleArray() {
return asPrimitiveArray();
}
@Override @Override
public PrimitiveIterator.OfDouble iterator() { public PrimitiveIterator.OfDouble iterator() {
return Spliterators.iterator(spliterator()); return Spliterators.iterator(spliterator());
...@@ -925,6 +990,19 @@ class SpinedBuffer<E> ...@@ -925,6 +990,19 @@ class SpinedBuffer<E>
public Spliterator.OfDouble spliterator() { public Spliterator.OfDouble spliterator() {
class Splitr extends BaseSpliterator<Spliterator.OfDouble> class Splitr extends BaseSpliterator<Spliterator.OfDouble>
implements Spliterator.OfDouble { implements Spliterator.OfDouble {
Splitr(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
super(firstSpineIndex, lastSpineIndex,
firstSpineElementIndex, lastSpineElementFence);
}
@Override
Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex,
int firstSpineElementIndex, int lastSpineElementFence) {
return new Splitr(firstSpineIndex, lastSpineIndex,
firstSpineElementIndex, lastSpineElementFence);
}
@Override @Override
void arrayForOne(double[] array, int index, DoubleConsumer consumer) { void arrayForOne(double[] array, int index, DoubleConsumer consumer) {
consumer.accept(array[index]); consumer.accept(array[index]);
...@@ -935,12 +1013,12 @@ class SpinedBuffer<E> ...@@ -935,12 +1013,12 @@ class SpinedBuffer<E>
return Arrays.spliterator(array, offset, offset+len); return Arrays.spliterator(array, offset, offset+len);
} }
} }
return new Splitr(); return new Splitr(0, spineIndex, 0, elementIndex);
} }
@Override @Override
public String toString() { public String toString() {
double[] array = asDoubleArray(); double[] array = asPrimitiveArray();
if (array.length < 200) { if (array.length < 200) {
return String.format("%s[length=%d, chunks=%d]%s", return String.format("%s[length=%d, chunks=%d]%s",
getClass().getSimpleName(), array.length, getClass().getSimpleName(), array.length,
......
...@@ -122,12 +122,12 @@ public class DoubleNodeTest extends OpTestCase { ...@@ -122,12 +122,12 @@ public class DoubleNodeTest extends OpTestCase {
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
public void testAsArray(double[] array, Node.OfDouble n) { public void testAsArray(double[] array, Node.OfDouble n) {
assertEquals(n.asDoubleArray(), array); assertEquals(n.asPrimitiveArray(), array);
} }
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
public void testFlattenAsArray(double[] array, Node.OfDouble n) { public void testFlattenAsArray(double[] array, Node.OfDouble n) {
assertEquals(Nodes.flattenDouble(n).asDoubleArray(), array); assertEquals(Nodes.flattenDouble(n).asPrimitiveArray(), array);
} }
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
......
...@@ -122,12 +122,12 @@ public class IntNodeTest extends OpTestCase { ...@@ -122,12 +122,12 @@ public class IntNodeTest extends OpTestCase {
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
public void testAsArray(int[] array, Node.OfInt n) { public void testAsArray(int[] array, Node.OfInt n) {
assertEquals(n.asIntArray(), array); assertEquals(n.asPrimitiveArray(), array);
} }
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
public void testFlattenAsArray(int[] array, Node.OfInt n) { public void testFlattenAsArray(int[] array, Node.OfInt n) {
assertEquals(Nodes.flattenInt(n).asIntArray(), array); assertEquals(Nodes.flattenInt(n).asPrimitiveArray(), array);
} }
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
......
...@@ -122,12 +122,12 @@ public class LongNodeTest extends OpTestCase { ...@@ -122,12 +122,12 @@ public class LongNodeTest extends OpTestCase {
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
public void testAsArray(long[] array, Node.OfLong n) { public void testAsArray(long[] array, Node.OfLong n) {
assertEquals(n.asLongArray(), array); assertEquals(n.asPrimitiveArray(), array);
} }
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
public void testFlattenAsArray(long[] array, Node.OfLong n) { public void testFlattenAsArray(long[] array, Node.OfLong n) {
assertEquals(Nodes.flattenLong(n).asLongArray(), array); assertEquals(Nodes.flattenLong(n).asPrimitiveArray(), array);
} }
@Test(dataProvider = "nodes") @Test(dataProvider = "nodes")
......
...@@ -210,7 +210,7 @@ public class SpinedBufferTest { ...@@ -210,7 +210,7 @@ public class SpinedBufferTest {
list2.clear(); list2.clear();
sb.forEach((int i) -> list2.add(i)); sb.forEach((int i) -> list2.add(i));
assertEquals(list1, list2); assertEquals(list1, list2);
int[] array = sb.asIntArray(); int[] array = sb.asPrimitiveArray();
list2.clear(); list2.clear();
for (int i : array) for (int i : array)
list2.add(i); list2.add(i);
...@@ -285,7 +285,7 @@ public class SpinedBufferTest { ...@@ -285,7 +285,7 @@ public class SpinedBufferTest {
list2.clear(); list2.clear();
sb.forEach((long i) -> list2.add(i)); sb.forEach((long i) -> list2.add(i));
assertEquals(list1, list2); assertEquals(list1, list2);
long[] array = sb.asLongArray(); long[] array = sb.asPrimitiveArray();
list2.clear(); list2.clear();
for (long i : array) for (long i : array)
list2.add(i); list2.add(i);
...@@ -361,7 +361,7 @@ public class SpinedBufferTest { ...@@ -361,7 +361,7 @@ public class SpinedBufferTest {
list2.clear(); list2.clear();
sb.forEach((double i) -> list2.add(i)); sb.forEach((double i) -> list2.add(i));
assertEquals(list1, list2); assertEquals(list1, list2);
double[] array = sb.asDoubleArray(); double[] array = sb.asPrimitiveArray();
list2.clear(); list2.clear();
for (double i : array) for (double i : array)
list2.add(i); list2.add(i);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册