diff --git a/CHANGE_LOG.md b/CHANGE_LOG.md index e7550b2..8a09fdc 100644 --- a/CHANGE_LOG.md +++ b/CHANGE_LOG.md @@ -1,15 +1,15 @@ -# CHANGE LOG - -## 0.3.7 -1. Bug fix on `YieldIterator` that caused thread to block forever if `#hasNext()` was called again -times it returned `false`. - -## 0.3.6 -1. Added `InputStreamSupplier#forInputStream( in )` which will parse the given InputStream to determine the encoding -and return a single use `InputStreamSupplier` instance whose get() call can only be called once. - -## 0.3.5 - -1. changed collection of cachedSuppliers from ArrayList to ConcurrentLinkedDeque so we can safely manipulate group concurrently. -1. added `CachedSupplier#ofInitializer()` methods which take Suppliers and return `CachedSupplier` +# CHANGE LOG + +## 0.3.7 +1. Bug fix on `YieldIterator` that caused thread to block forever if `#hasNext()` was called again. +1. use primitive int iterator when possible for performance improvement + +## 0.3.6 +1. Added `InputStreamSupplier#forInputStream( in )` which will parse the given InputStream to determine the encoding +and return a single use `InputStreamSupplier` instance whose get() call can only be called once. + +## 0.3.5 + +1. changed collection of cachedSuppliers from ArrayList to ConcurrentLinkedDeque so we can safely manipulate group concurrently. +1. added `CachedSupplier#ofInitializer()` methods which take Suppliers and return `CachedSupplier` so clients don't have to make Suppliers that return null. \ No newline at end of file diff --git a/pom.xml b/pom.xml index fd09b32..380dbf5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,221 +1,221 @@ - - - - 4.0.0 - gov.nih.ncats - ncats-common - jar - 0.3.7-SNAPSHOT - ncats-common - - https://github.com/ncats/ncats-common - Common utility classes used in several NIH/NCATS projects. - - NIH/NCATS - https://ncats.nih.gov - - - - Apache-2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - - katzelda - Daniel Katzel - daniel.katzel@nih.gov - - architect - developer - - America/New_York - - - peryeata - Tyler Peryea - tyler.peryea@nih.gov - - architect - developer - - America/New_York - - - nguyenda - Dac-Trung Nguyen - dactrung.nguyen@nih.gov - - architect - developer - - America/New_York - - - - - https://github.com/ncats/ncats-common.git - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - - junit - junit - 4.13.1 - test - - - - com.fasterxml.jackson.core - jackson-annotations - 2.9.9 - provided - - - org.mockito - mockito-core - 3.3.3 - test - - - - - - - maven-compiler-plugin - 3.5.1 - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - - attach-javadocs - - jar - - - false - false - 1.8 - http://docs.oracle.com/javase/7/docs/api/ http://docs.oracle.com/javase/7/docs/api/ - none - - - - - - - - - - ossrh - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.7 - true - - ossrh - https://oss.sonatype.org/ - true - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - - attach-javadocs - - jar - - - - - - - - - - + + + + 4.0.0 + gov.nih.ncats + ncats-common + jar + 0.3.7 + ncats-common + + https://github.com/ncats/ncats-common + Common utility classes used in several NIH/NCATS projects. + + NIH/NCATS + https://ncats.nih.gov + + + + Apache-2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + katzelda + Daniel Katzel + daniel.katzel@nih.gov + + architect + developer + + America/New_York + + + peryeata + Tyler Peryea + tyler.peryea@nih.gov + + architect + developer + + America/New_York + + + nguyenda + Dac-Trung Nguyen + dactrung.nguyen@nih.gov + + architect + developer + + America/New_York + + + + + https://github.com/ncats/ncats-common.git + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + junit + junit + 4.13.1 + test + + + + com.fasterxml.jackson.core + jackson-annotations + 2.9.9 + provided + + + org.mockito + mockito-core + 3.3.3 + test + + + + + + + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + false + false + 1.8 + http://docs.oracle.com/javase/7/docs/api/ http://docs.oracle.com/javase/7/docs/api/ + none + + + + + + + + + + ossrh + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + + + + + + diff --git a/src/main/java/gov/nih/ncats/common/iter/PrimitiveArrayIterators.java b/src/main/java/gov/nih/ncats/common/iter/PrimitiveArrayIterators.java index e1da169..1e192a6 100644 --- a/src/main/java/gov/nih/ncats/common/iter/PrimitiveArrayIterators.java +++ b/src/main/java/gov/nih/ncats/common/iter/PrimitiveArrayIterators.java @@ -1,520 +1,524 @@ -/* - * NCATS-COMMON - * - * Copyright 2020 NIH/NCATS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package gov.nih.ncats.common.iter; - - -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * {@code PrimitiveArrayIterators} - * provides factory methods to create - * {@link Iterator} of boxed primitives - * that iterate over primitive arrays. - * the Boxing is performed one element at a - * time and only when {@link Iterator#next()} - * is called. - *

- * None of the returned iterators - * are thread-safe. - * @author dkatzel - * - */ -public final class PrimitiveArrayIterators { - - private PrimitiveArrayIterators(){ - //can not instantiate - } - /** - * Create a new Iterator that will - * iterate over all the elements - * of the given array. The iterator - * does NOT copy the array so any changes - * to the array while iterating - * will be reflected in the array. - * @param array the array of primitives - * to iterate over; can not be null. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - */ - public static Iterator create(int[] array){ - return new IntIterator(array,0, array.length-1); - } - /** - * Create a new Iterator that will - * iterate over {@code length} elements - * of the given array starting at the offset 0. - * @param array the array of primitives - * to iterate over; can not be null. - * @param length the number of elements to iterate - * over; must be <= array.length and >=0. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if length < 0. or if the length - * is longer than the given array. - */ - public static Iterator create(int[] array, int length){ - int arrayLength = array.length; - validateParameters(length, arrayLength); - if(length==0){ - return IteratorUtil.createEmptyIterator(); - } - return new IntIterator(array,0, length-1); - } - public static void validateParameters(int length, int arrayLength) { - if(length > arrayLength){ - throw new IllegalArgumentException("given length must be <= array.length"); - } - if(length<0){ - throw new IllegalArgumentException("length must be >=0"); - } - } - /** - * Create a new Iterator that will start - * at the specified start offset (inclusive) - * and end at the specified end offset (also inclusive). - * @param array the array of primitives - * to iterate over; can not be null. - * @param start the start offset (inclusive) - * to begin iterating, must be a valid offset into - * the array. - * @param end the end offset (inclusive) - * to stop iterating, must be a valid offset into - * the array. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if start is greater - * than the end. - * @throws ArrayIndexOutOfBoundsException if either start - * or end are out of bounds of the array. - */ - public static Iterator create(int[] array, int start, int end){ - validateParameters(start, end, array.length); - return new IntIterator(array,start, end); - } - public static void validateParameters(int start, int end, int arrayLength) { - if(start < 0 || start >= arrayLength){ - throw new ArrayIndexOutOfBoundsException("start " + start + " array length = " + arrayLength); - } - if(end < 0 || end >= arrayLength){ - throw new ArrayIndexOutOfBoundsException("end " + end +" array length = " + arrayLength); - } - if(start >end){ - throw new IllegalArgumentException("start > end" + start + " " + end ); - } - } - - /** - * Create a new Iterator that will - * iterate over all the elements - * of the given array. - * @param array the array of primitives - * to iterate over; can not be null. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - */ - public static Iterator create(byte[] array){ - return new ByteIterator(array,0, array.length-1); - } - /** - * Create a new Iterator that will - * iterate over {@code length} elements - * of the given array starting at the offset 0. - * @param array the array of primitives - * to iterate over; can not be null. - * @param length the number of elements to iterate - * over; must be <= array.length and >=0. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if length < 0. or if the length - * is longer than the given array. - */ - public static Iterator create(byte[] array, int length){ - int arrayLength = array.length; - validateParameters(length, arrayLength); - if(length==0){ - return IteratorUtil.createEmptyIterator(); - } - return new ByteIterator(array,0, length-1); - } - /** - * Create a new Iterator that will start - * at the specified start offset (inclusive) - * and end at the specified end offset (also inclusive). - * @param array the array of primitives - * to iterate over; can not be null. - * @param start the start offset (inclusive) - * to begin iterating, must be a valid offset into - * the array. - * @param end the end offset (inclusive) - * to stop iterating, must be a valid offset into - * the array. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if start is greater - * than the end. - * @throws ArrayIndexOutOfBoundsException if either start - * or end are out of bounds of the array. - */ - public static Iterator create(byte[] array, int start, int end){ - validateParameters(start, end, array.length); - return new ByteIterator(array,start, end); - } - - /** - * Create a new Iterator that will - * iterate over all the elements - * of the given array. - * @param array the array of primitives - * to iterate over; can not be null. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - */ - public static Iterator create(short[] array){ - return new ShortIterator(array,0, array.length-1); - } - /** - * Create a new Iterator that will - * iterate over {@code length} elements - * of the given array starting at the offset 0. - * @param array the array of primitives - * to iterate over; can not be null. - * @param length the number of elements to iterate - * over; must be <= array.length and >=0. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if length < 0. or if the length - * is longer than the given array. - */ - public static Iterator create(short[] array, int length){ - int arrayLength = array.length; - validateParameters(length,arrayLength); - if(length==0){ - return IteratorUtil.createEmptyIterator(); - } - return new ShortIterator(array,0, length-1); - } - /** - * Create a new Iterator that will start - * at the specified start offset (inclusive) - * and end at the specified end offset (also inclusive). - * @param array the array of primitives - * to iterate over; can not be null. - * @param start the start offset (inclusive) - * to begin iterating, must be a valid offset into - * the array. - * @param end the end offset (inclusive) - * to stop iterating, must be a valid offset into - * the array. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if start is greater - * than the end. - * @throws ArrayIndexOutOfBoundsException if either start - * or end are out of bounds of the array. - */ - public static Iterator create(short[] array, int start, int end){ - validateParameters(start, end, array.length); - return new ShortIterator(array,start, end); - } - - - /** - * Create a new Iterator that will - * iterate over all the elements - * of the given array. - * @param array the array of primitives - * to iterate over; can not be null. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - */ - public static Iterator create(char[] array){ - return new CharIterator(array,0, array.length-1); - } - /** - * Create a new Iterator that will - * iterate over {@code length} elements - * of the given array starting at the offset 0. - * @param array the array of primitives - * to iterate over; can not be null. - * @param length the number of elements to iterate - * over; must be <= array.length and >=0. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if length < 0. or if the length - * is longer than the given array. - */ - public static Iterator create(char[] array, int length){ - int arrayLength = array.length; - validateParameters(length,arrayLength); - if(length==0){ - return IteratorUtil.createEmptyIterator(); - } - return new CharIterator(array,0, length-1); - } - /** - * Create a new Iterator that will start - * at the specified start offset (inclusive) - * and end at the specified end offset (also inclusive). - * @param array the array of primitives - * to iterate over; can not be null. - * @param start the start offset (inclusive) - * to begin iterating, must be a valid offset into - * the array. - * @param end the end offset (inclusive) - * to stop iterating, must be a valid offset into - * the array. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if start is greater - * than the end. - * @throws ArrayIndexOutOfBoundsException if either start - * or end are out of bounds of the array. - */ - public static Iterator create(char[] array, int start, int end){ - validateParameters(start, end, array.length); - return new CharIterator(array,start, end); - } - - /** - * Create a new Iterator that will - * iterate over all the elements - * of the given array. - * @param array the array of primitives - * to iterate over; can not be null. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - */ - public static Iterator create(long[] array){ - return new LongIterator(array,0, array.length-1); - } - /** - * Create a new Iterator that will - * iterate over {@code length} elements - * of the given array starting at the offset 0. - * @param array the array of primitives - * to iterate over; can not be null. - * @param length the number of elements to iterate - * over; must be <= array.length and >=1. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if length < 1. or if the length - * is longer than the given array. - */ - public static Iterator create(long[] array, int length){ - int arrayLength = array.length; - validateParameters(length, arrayLength); - if(length==0){ - return IteratorUtil.createEmptyIterator(); - } - return new LongIterator(array,0, length-1); - } - /** - * Create a new Iterator that will start - * at the specified start offset (inclusive) - * and end at the specified end offset (also inclusive). - * @param array the array of primitives - * to iterate over; can not be null. - * @param start the start offset (inclusive) - * to begin iterating, must be a valid offset into - * the array. - * @param end the end offset (inclusive) - * to stop iterating, must be a valid offset into - * the array. - * @return a new Iterator will never be null. - * @throws NullPointerException if array is null. - * @throws IllegalArgumentException if start is greater - * than the end. - * @throws ArrayIndexOutOfBoundsException if either start - * or end are out of bounds of the array. - */ - public static Iterator create(long[] array, int start, int end){ - validateParameters(start, end, array.length); - return new LongIterator(array,start, end); - } - - private static class IntIterator implements Iterator{ - - private final int[] array; - private int currentOffset; - private final int endOffset; - - public IntIterator(int[] array, int start, int end){ - this.array = array; - this.endOffset = end; - this.currentOffset = start; - } - - @Override - public boolean hasNext() { - return currentOffset<=endOffset; - } - - @Override - public Integer next() { - if(!hasNext()){ - throw new NoSuchElementException(); - } - Integer next =array[currentOffset]; - currentOffset++; - return next; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - } - - private static class ByteIterator implements Iterator{ - - private final byte[] array; - private int currentOffset; - private final int endOffset; - - public ByteIterator(byte[] array, int start, int end){ - this.array = array; - this.endOffset = end; - this.currentOffset = start; - } - - @Override - public boolean hasNext() { - return currentOffset<=endOffset; - } - - @Override - public Byte next() { - if(!hasNext()){ - throw new NoSuchElementException(); - } - Byte next =array[currentOffset]; - currentOffset++; - return next; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - } - - private static class ShortIterator implements Iterator{ - - private final short[] array; - private int currentOffset; - private final int endOffset; - - public ShortIterator(short[] array, int start, int end){ - this.array = array; - this.endOffset = end; - this.currentOffset = start; - } - - @Override - public boolean hasNext() { - return currentOffset<=endOffset; - } - - @Override - public Short next() { - if(!hasNext()){ - throw new NoSuchElementException(); - } - Short next =array[currentOffset]; - currentOffset++; - return next; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - } - - private static class CharIterator implements Iterator{ - - private final char[] array; - private int currentOffset; - private final int endOffset; - - public CharIterator(char[] array, int start, int end){ - this.array = array; - this.endOffset = end; - this.currentOffset = start; - } - - @Override - public boolean hasNext() { - return currentOffset<=endOffset; - } - - @Override - public Character next() { - if(!hasNext()){ - throw new NoSuchElementException(); - } - Character next =array[currentOffset]; - currentOffset++; - return next; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - } - - private static class LongIterator implements Iterator{ - - private final long[] array; - private int currentOffset; - private final int endOffset; - - public LongIterator(long[] array, int start, int end){ - this.array = array; - this.endOffset = end; - this.currentOffset = start; - } - - @Override - public boolean hasNext() { - return currentOffset<=endOffset; - } - - @Override - public Long next() { - if(!hasNext()){ - throw new NoSuchElementException(); - } - Long next =array[currentOffset]; - currentOffset++; - return next; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - } -} +/* + * NCATS-COMMON + * + * Copyright 2020 NIH/NCATS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package gov.nih.ncats.common.iter; + + +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.PrimitiveIterator.OfInt; + +/** + * {@code PrimitiveArrayIterators} + * provides factory methods to create + * {@link Iterator} of boxed primitives + * that iterate over primitive arrays. + * the Boxing is performed one element at a + * time and only when {@link Iterator#next()} + * is called. + *

+ * None of the returned iterators + * are thread-safe. + * @author dkatzel + * + */ +public final class PrimitiveArrayIterators { + + private PrimitiveArrayIterators(){ + //can not instantiate + } + /** + * Create a new Iterator that will + * iterate over all the elements + * of the given array. The iterator + * does NOT copy the array so any changes + * to the array while iterating + * will be reflected in the array. + * @param array the array of primitives + * to iterate over; can not be null. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + */ + public static OfInt create(int[] array){ + return new IntIterator(array,0, array.length-1); + } + /** + * Create a new Iterator that will + * iterate over {@code length} elements + * of the given array starting at the offset 0. + * @param array the array of primitives + * to iterate over; can not be null. + * @param length the number of elements to iterate + * over; must be <= array.length and >=0. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if length < 0. or if the length + * is longer than the given array. + */ + public static OfInt create(int[] array, int length){ + int arrayLength = array.length; + validateParameters(length, arrayLength); + + return new IntIterator(array,0, length-1); + } + public static void validateParameters(int length, int arrayLength) { + if(length > arrayLength){ + throw new IllegalArgumentException("given length must be <= array.length"); + } + if(length<0){ + throw new IllegalArgumentException("length must be >=0"); + } + } + /** + * Create a new Iterator that will start + * at the specified start offset (inclusive) + * and end at the specified end offset (also inclusive). + * @param array the array of primitives + * to iterate over; can not be null. + * @param start the start offset (inclusive) + * to begin iterating, must be a valid offset into + * the array. + * @param end the end offset (inclusive) + * to stop iterating, must be a valid offset into + * the array. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if start is greater + * than the end. + * @throws ArrayIndexOutOfBoundsException if either start + * or end are out of bounds of the array. + */ + public static Iterator create(int[] array, int start, int end){ + validateParameters(start, end, array.length); + return new IntIterator(array,start, end); + } + public static void validateParameters(int start, int end, int arrayLength) { + if(start < 0 || start >= arrayLength){ + throw new ArrayIndexOutOfBoundsException("start " + start + " array length = " + arrayLength); + } + if(end < 0 || end >= arrayLength){ + throw new ArrayIndexOutOfBoundsException("end " + end +" array length = " + arrayLength); + } + if(start >end){ + throw new IllegalArgumentException("start > end" + start + " " + end ); + } + } + + /** + * Create a new Iterator that will + * iterate over all the elements + * of the given array. + * @param array the array of primitives + * to iterate over; can not be null. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + */ + public static Iterator create(byte[] array){ + return new ByteIterator(array,0, array.length-1); + } + /** + * Create a new Iterator that will + * iterate over {@code length} elements + * of the given array starting at the offset 0. + * @param array the array of primitives + * to iterate over; can not be null. + * @param length the number of elements to iterate + * over; must be <= array.length and >=0. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if length < 0. or if the length + * is longer than the given array. + */ + public static Iterator create(byte[] array, int length){ + int arrayLength = array.length; + validateParameters(length, arrayLength); + if(length==0){ + return IteratorUtil.createEmptyIterator(); + } + return new ByteIterator(array,0, length-1); + } + /** + * Create a new Iterator that will start + * at the specified start offset (inclusive) + * and end at the specified end offset (also inclusive). + * @param array the array of primitives + * to iterate over; can not be null. + * @param start the start offset (inclusive) + * to begin iterating, must be a valid offset into + * the array. + * @param end the end offset (inclusive) + * to stop iterating, must be a valid offset into + * the array. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if start is greater + * than the end. + * @throws ArrayIndexOutOfBoundsException if either start + * or end are out of bounds of the array. + */ + public static Iterator create(byte[] array, int start, int end){ + validateParameters(start, end, array.length); + return new ByteIterator(array,start, end); + } + + /** + * Create a new Iterator that will + * iterate over all the elements + * of the given array. + * @param array the array of primitives + * to iterate over; can not be null. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + */ + public static Iterator create(short[] array){ + return new ShortIterator(array,0, array.length-1); + } + /** + * Create a new Iterator that will + * iterate over {@code length} elements + * of the given array starting at the offset 0. + * @param array the array of primitives + * to iterate over; can not be null. + * @param length the number of elements to iterate + * over; must be <= array.length and >=0. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if length < 0. or if the length + * is longer than the given array. + */ + public static Iterator create(short[] array, int length){ + int arrayLength = array.length; + validateParameters(length,arrayLength); + if(length==0){ + return IteratorUtil.createEmptyIterator(); + } + return new ShortIterator(array,0, length-1); + } + /** + * Create a new Iterator that will start + * at the specified start offset (inclusive) + * and end at the specified end offset (also inclusive). + * @param array the array of primitives + * to iterate over; can not be null. + * @param start the start offset (inclusive) + * to begin iterating, must be a valid offset into + * the array. + * @param end the end offset (inclusive) + * to stop iterating, must be a valid offset into + * the array. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if start is greater + * than the end. + * @throws ArrayIndexOutOfBoundsException if either start + * or end are out of bounds of the array. + */ + public static Iterator create(short[] array, int start, int end){ + validateParameters(start, end, array.length); + return new ShortIterator(array,start, end); + } + + + /** + * Create a new Iterator that will + * iterate over all the elements + * of the given array. + * @param array the array of primitives + * to iterate over; can not be null. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + */ + public static Iterator create(char[] array){ + return new CharIterator(array,0, array.length-1); + } + /** + * Create a new Iterator that will + * iterate over {@code length} elements + * of the given array starting at the offset 0. + * @param array the array of primitives + * to iterate over; can not be null. + * @param length the number of elements to iterate + * over; must be <= array.length and >=0. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if length < 0. or if the length + * is longer than the given array. + */ + public static Iterator create(char[] array, int length){ + int arrayLength = array.length; + validateParameters(length,arrayLength); + if(length==0){ + return IteratorUtil.createEmptyIterator(); + } + return new CharIterator(array,0, length-1); + } + /** + * Create a new Iterator that will start + * at the specified start offset (inclusive) + * and end at the specified end offset (also inclusive). + * @param array the array of primitives + * to iterate over; can not be null. + * @param start the start offset (inclusive) + * to begin iterating, must be a valid offset into + * the array. + * @param end the end offset (inclusive) + * to stop iterating, must be a valid offset into + * the array. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if start is greater + * than the end. + * @throws ArrayIndexOutOfBoundsException if either start + * or end are out of bounds of the array. + */ + public static Iterator create(char[] array, int start, int end){ + validateParameters(start, end, array.length); + return new CharIterator(array,start, end); + } + + /** + * Create a new Iterator that will + * iterate over all the elements + * of the given array. + * @param array the array of primitives + * to iterate over; can not be null. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + */ + public static Iterator create(long[] array){ + return new LongIterator(array,0, array.length-1); + } + /** + * Create a new Iterator that will + * iterate over {@code length} elements + * of the given array starting at the offset 0. + * @param array the array of primitives + * to iterate over; can not be null. + * @param length the number of elements to iterate + * over; must be <= array.length and >=1. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if length < 1. or if the length + * is longer than the given array. + */ + public static Iterator create(long[] array, int length){ + int arrayLength = array.length; + validateParameters(length, arrayLength); + if(length==0){ + return IteratorUtil.createEmptyIterator(); + } + return new LongIterator(array,0, length-1); + } + /** + * Create a new Iterator that will start + * at the specified start offset (inclusive) + * and end at the specified end offset (also inclusive). + * @param array the array of primitives + * to iterate over; can not be null. + * @param start the start offset (inclusive) + * to begin iterating, must be a valid offset into + * the array. + * @param end the end offset (inclusive) + * to stop iterating, must be a valid offset into + * the array. + * @return a new Iterator will never be null. + * @throws NullPointerException if array is null. + * @throws IllegalArgumentException if start is greater + * than the end. + * @throws ArrayIndexOutOfBoundsException if either start + * or end are out of bounds of the array. + */ + public static Iterator create(long[] array, int start, int end){ + validateParameters(start, end, array.length); + return new LongIterator(array,start, end); + } + + private static class IntIterator implements Iterator, OfInt{ + + private final int[] array; + private int currentOffset; + private final int endOffset; + + public IntIterator(int[] array, int start, int end){ + this.array = array; + this.endOffset = end; + this.currentOffset = start; + } + + @Override + public boolean hasNext() { + return currentOffset<=endOffset; + } + + @Override + public Integer next() { + return nextInt(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public int nextInt() { + if(!hasNext()){ + throw new NoSuchElementException(); + } + int next =array[currentOffset]; + currentOffset++; + return next; + } + + } + + private static class ByteIterator implements Iterator{ + + private final byte[] array; + private int currentOffset; + private final int endOffset; + + public ByteIterator(byte[] array, int start, int end){ + this.array = array; + this.endOffset = end; + this.currentOffset = start; + } + + @Override + public boolean hasNext() { + return currentOffset<=endOffset; + } + + @Override + public Byte next() { + if(!hasNext()){ + throw new NoSuchElementException(); + } + Byte next =array[currentOffset]; + currentOffset++; + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + + private static class ShortIterator implements Iterator{ + + private final short[] array; + private int currentOffset; + private final int endOffset; + + public ShortIterator(short[] array, int start, int end){ + this.array = array; + this.endOffset = end; + this.currentOffset = start; + } + + @Override + public boolean hasNext() { + return currentOffset<=endOffset; + } + + @Override + public Short next() { + if(!hasNext()){ + throw new NoSuchElementException(); + } + Short next =array[currentOffset]; + currentOffset++; + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + + private static class CharIterator implements Iterator{ + + private final char[] array; + private int currentOffset; + private final int endOffset; + + public CharIterator(char[] array, int start, int end){ + this.array = array; + this.endOffset = end; + this.currentOffset = start; + } + + @Override + public boolean hasNext() { + return currentOffset<=endOffset; + } + + @Override + public Character next() { + if(!hasNext()){ + throw new NoSuchElementException(); + } + Character next =array[currentOffset]; + currentOffset++; + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } + + private static class LongIterator implements Iterator{ + + private final long[] array; + private int currentOffset; + private final int endOffset; + + public LongIterator(long[] array, int start, int end){ + this.array = array; + this.endOffset = end; + this.currentOffset = start; + } + + @Override + public boolean hasNext() { + return currentOffset<=endOffset; + } + + @Override + public Long next() { + if(!hasNext()){ + throw new NoSuchElementException(); + } + Long next =array[currentOffset]; + currentOffset++; + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + } +} diff --git a/src/main/java/gov/nih/ncats/common/util/GrowableIntArray.java b/src/main/java/gov/nih/ncats/common/util/GrowableIntArray.java index 470454c..ccadbbb 100644 --- a/src/main/java/gov/nih/ncats/common/util/GrowableIntArray.java +++ b/src/main/java/gov/nih/ncats/common/util/GrowableIntArray.java @@ -1,539 +1,550 @@ -/* - * NCATS-COMMON - * - * Copyright 2020 NIH/NCATS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package gov.nih.ncats.common.util; - - -import gov.nih.ncats.common.functions.ThrowingIntIndexedIntConsumer; -import gov.nih.ncats.common.iter.PrimitiveArrayIterators; - -import java.util.*; -import java.util.stream.IntStream; - -/** - * A {@code GrowableIntArray} is a utility class - * that wraps a int array that will dynamically - * grow as needed when data is - * appended, inserted, replaced and removed etc. - * This is similar to an {@link ArrayList} - * or {@link StringBuilder} - * for primitive shorts. - * This class is not Thread-safe. - * @author dkatzel - * - */ -public final class GrowableIntArray implements Iterable{ - /** - * The current length of valid data - * this is not the same as the length - * of the int array (capacity) since - * there still might be room to grow. - * There might even be old data in the array - * past current length if the array - * has been modified via the {@link #remove(int)} - * methods. - */ - private int currentLength=0; - /** - * Our actual int array, - * the capacity is the size of the array. - */ - private int[] data; - /** - * Creates a new Growable array - * with the given initial capacity. - * @param initialCapacity the initial size - * of the backing int array. When adding - * ints will cause the int array to overflow, - * the backing int array will automatically - * grow larger. - * @throws IllegalArgumentException if initialCapacity is <0. - */ - public GrowableIntArray(int initialCapacity){ - if(initialCapacity <0){ - throw new IllegalArgumentException("initial capacity should be >= 0 :"+initialCapacity); - } - data = new int[initialCapacity]; - } - /** - * Creates a new Growable array - * where the backing array contains - * the contents of the given Collection - * stored as primitives. The order in the array - * is the determined by the Collection's iteration order. - * The capacity and length of this growable array - * are set to the collection's size. - * @param ints the Collection of Integers to - * create into a growable array from. - * @throws NullPointerException if the given - * collection is null or any elements in the collection - * are null. - */ - public GrowableIntArray(Collection ints){ - data = new int[ints.size()]; - int index=0; - for(Integer i : ints){ - data[index]=i.intValue(); - index++; - } - currentLength=data.length; - } - /** - * Creates a new Growable array - * where the backing int array is an exact - * copy of the input array and the initial - * capacity is set to the array length. - * This has similar (although optimized) - * functionality to - *

-	 * int[] ints = ...
-	 * GrowableIntArray gba = new GrowableIntArray(ints.length);
-	 * gba.append(int);
-	 * 
- * @param ints the initial short values to set - * to the backing array. - * @throws NullPointerException if ints is null. - */ - public GrowableIntArray(int[] ints){ - data = Arrays.copyOf(ints, ints.length); - currentLength=data.length; - } - private GrowableIntArray(GrowableIntArray copy){ - data = Arrays.copyOf(copy.data, copy.data.length); - currentLength = copy.currentLength; - } - /** - * Creates a new Growable array - * with a default initial capacity. - */ - public GrowableIntArray() { - this(16); - } - /** - * Create a new instance of GrowableShortArray - * that is an exact copy of this instance. - * Any future modifications to either the original - * instance or the copy will NOT be reflected - * in the other. - * @return a new instance of GrowableIntArray - * that contains the same data as this instance - * currently does. - */ - public GrowableIntArray copy(){ - return new GrowableIntArray(this); - } - private void assertValidOffset(int offset) { - if (offset <0 || offset >= currentLength){ - throw new IndexOutOfBoundsException( - "Index: "+offset+", Size: "+currentLength); - } - } - private void assertValidRange(Range range) { - if (range.getBegin()<0 || range.getEnd() >= currentLength){ - throw new IndexOutOfBoundsException( - "range: "+range+", array size: "+currentLength); - } - } - - public void reverse(){ - int pivotPoint = currentLength/2; - for(int i=0; i 0){ - System.arraycopy(data, (int)range.getEnd()+1, - data, (int)range.getBegin(), numMoved); - } - currentLength-=(int)range.getLength(); - } - public int remove(int offset){ - assertValidOffset(offset); - int oldValue = data[offset]; - - int numMoved = currentLength - offset - 1; - if (numMoved > 0){ - System.arraycopy(data, offset+1, data, offset, numMoved); - } - currentLength--; - return oldValue; - } - /** - * Get the current capacity of the backing - * array. This may be larger than the value - * returned by {@link #getCurrentLength()}. - * Modifying this growable array to extend - * beyond the current capacity will require - * the backing array to be grown. - * @return the current capacity; - * will always be >=0; - */ - public int getCurrentCapacity(){ - return data.length; - } - - private void ensureCapacity(int minCapacity) { - int oldCapacity = data.length; - if (minCapacity > oldCapacity) { - //algorithm borrowed from ArrayList - int newCapacity = (oldCapacity * 3)/2 + 1; - if (newCapacity < minCapacity){ - newCapacity = minCapacity; - } - // minCapacity is usually close to size, so this is a win: - data = Arrays.copyOf(data, newCapacity); - } - } - - public int[] toArray(){ - return Arrays.copyOf(data,currentLength); - } - /** - * Searches the current values in this growable array - * using the binary search algorithm as implemented - * by {@link Arrays#binarySearch(int[], int)}. - * The array must be sorted (as - * by the {@link #sort()} method) prior to making this call. If it - * is not sorted, the results are undefined. If the array contains - * multiple elements with the specified value, there is no guarantee which - * one will be found. - * - * @param key the value to be searched for. - * @return index of the search key, if it is contained in the array; - * otherwise, (-(insertion point) - 1). The - * insertion point is defined as the point at which the - * key would be inserted into the array: the index of the first - * element greater than the key, or a.length if all - * elements in the array are less than the specified key. Note - * that this guarantees that the return value will be >= 0 if - * and only if the key is found. - * @throws IllegalArgumentException - * if {@code fromIndex > toIndex} - * @throws ArrayIndexOutOfBoundsException - * if {@code fromIndex < 0 or toIndex > a.length} - *@see Arrays#binarySearch(byte[], byte) - */ - public int binarySearch(int key){ - return Arrays.binarySearch(data, 0, currentLength, key); - } - /** - * Remove the given value from this - * sorted array. This method - * assumes that the values in the backing - * array have been previously sorted. - * If this sorted array contains several - * indexes with this value - * then only one will be removed - * and it is undefined which one will - * actually be removed. - * Calling this method on an unsorted - * backing array may not remove the value - * correctly. - * @param value the value to remove - * @return {@code true} if the value - * was found and removed; {@code false} - * if the value does not exist in the - * sorted backing array. - */ - public boolean sortedRemove(int value){ - int index = binarySearch(value); - - if (index >= 0) { - remove(index); - return true; - } - return false; - } - /** - * Insert the given value into the - * sorted backing array. - * Calling this method on an unsorted - * backing array may not insert the value - * correctly. - * @param value the value to insert. - * @return the index that this value - * was inserted into. - */ - public int sortedInsert(int value){ - int index = binarySearch(value); - if(index <0){ - //not found - //value returned is (-insertion point) -1) - index = -index -1; - } - insert(index, value); - return index; - } - /** - * Insert the given sorted array of values into the - * sorted backing array. This should produce identical - * results - * to iterating over the array and calling - * {@link #sortedInsert(int)} on each element, - * but is hopefully more efficient. - * - * Calling this method on an unsorted - * backing array may not insert the value - * correctly. - * @param values the values to insert. - */ - public void sortedInsert(int[] values){ - if(values.length==0){ - //no-op - return; - } - if(currentLength ==0){ - //we have 0 length - //act just like append - append(values); - return; - } - int[] newData = new int[data.length + values.length]; - int newCurrentLength = currentLength + values.length; - - int ourDataIndex=0, otherDataIndex=0; - - int ourNextValue = data[0]; - int otherNextValue = values[0]; - int i=0; - for(; ourDataIndex iterator() { - return PrimitiveArrayIterators.create(data, currentLength); - } - /** - * Get the number of values - * in this array that currently - * have the given value. - * @param value the value to look for. - * @return the number of cells with - * the value; will always be >= 0. - */ - public int getCount(int value){ - int count=0; - for(int i=0; i toBoxedList() { - if(currentLength ==0){ - //return new list to make it mutable - return new ArrayList<>(); - } - return ArrayUtil.asList(toArray()); - } - - /** - * Iterate over each element in the list and call the given consumer - * which captures the offset and the value. - * @param consumer the consumer of each element; can not be null. - * @param the Throwable that might be thrown by the consumer. - * @throws E the Throwable from the consumer. - * - * - * - * @throws NullPointerException if consumer is null. - */ - public void forEachIndexed(ThrowingIntIndexedIntConsumer consumer) throws E{ - Objects.requireNonNull(consumer); - for(int i=0; i< currentLength; i++){ - consumer.accept(i, data[i]); - } - } - - /** - * Iterate over the elements in the given range of this array and call the given consumer - * which captures the offset and the value. - * @param consumer the consumer of each element; can not be null. - * @param the Throwable that might be thrown by the consumer. - * @throws E the Throwable from the consumer. - * - * - */ - public void forEachIndexed(Range range, ThrowingIntIndexedIntConsumer consumer) throws E{ - int end = (int) Math.min(currentLength, range.getEnd()+1); - for(int i=(int) range.getBegin(); i< end; i++){ - consumer.accept(i, data[i]); - } - } -} +/* + * NCATS-COMMON + * + * Copyright 2020 NIH/NCATS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package gov.nih.ncats.common.util; + + +import gov.nih.ncats.common.functions.ThrowingIntIndexedIntConsumer; +import gov.nih.ncats.common.iter.PrimitiveArrayIterators; + +import java.util.*; +import java.util.PrimitiveIterator.OfInt; +import java.util.stream.IntStream; + +/** + * A {@code GrowableIntArray} is a utility class + * that wraps a int array that will dynamically + * grow as needed when data is + * appended, inserted, replaced and removed etc. + * This is similar to an {@link ArrayList} + * or {@link StringBuilder} + * for primitive shorts. + * This class is not Thread-safe. + * @author dkatzel + * + */ +public final class GrowableIntArray implements Iterable{ + /** + * The current length of valid data + * this is not the same as the length + * of the int array (capacity) since + * there still might be room to grow. + * There might even be old data in the array + * past current length if the array + * has been modified via the {@link #remove(int)} + * methods. + */ + private int currentLength=0; + /** + * Our actual int array, + * the capacity is the size of the array. + */ + private int[] data; + /** + * Creates a new Growable array + * with the given initial capacity. + * @param initialCapacity the initial size + * of the backing int array. When adding + * ints will cause the int array to overflow, + * the backing int array will automatically + * grow larger. + * @throws IllegalArgumentException if initialCapacity is <0. + */ + public GrowableIntArray(int initialCapacity){ + if(initialCapacity <0){ + throw new IllegalArgumentException("initial capacity should be >= 0 :"+initialCapacity); + } + data = new int[initialCapacity]; + } + /** + * Creates a new Growable array + * where the backing array contains + * the contents of the given Collection + * stored as primitives. The order in the array + * is the determined by the Collection's iteration order. + * The capacity and length of this growable array + * are set to the collection's size. + * @param ints the Collection of Integers to + * create into a growable array from. + * @throws NullPointerException if the given + * collection is null or any elements in the collection + * are null. + */ + public GrowableIntArray(Collection ints){ + data = new int[ints.size()]; + int index=0; + for(Integer i : ints){ + data[index]=i.intValue(); + index++; + } + currentLength=data.length; + } + /** + * Creates a new Growable array + * where the backing int array is an exact + * copy of the input array and the initial + * capacity is set to the array length. + * This has similar (although optimized) + * functionality to + *
+	 * int[] ints = ...
+	 * GrowableIntArray gba = new GrowableIntArray(ints.length);
+	 * gba.append(int);
+	 * 
+ * @param ints the initial short values to set + * to the backing array. + * @throws NullPointerException if ints is null. + */ + public GrowableIntArray(int[] ints){ + data = Arrays.copyOf(ints, ints.length); + currentLength=data.length; + } + private GrowableIntArray(GrowableIntArray copy){ + data = Arrays.copyOf(copy.data, copy.data.length); + currentLength = copy.currentLength; + } + /** + * Creates a new Growable array + * with a default initial capacity. + */ + public GrowableIntArray() { + this(16); + } + /** + * Create a new instance of GrowableShortArray + * that is an exact copy of this instance. + * Any future modifications to either the original + * instance or the copy will NOT be reflected + * in the other. + * @return a new instance of GrowableIntArray + * that contains the same data as this instance + * currently does. + */ + public GrowableIntArray copy(){ + return new GrowableIntArray(this); + } + private void assertValidOffset(int offset) { + if (offset <0 || offset >= currentLength){ + throw new IndexOutOfBoundsException( + "Index: "+offset+", Size: "+currentLength); + } + } + private void assertValidRange(Range range) { + if (range.getBegin()<0 || range.getEnd() >= currentLength){ + throw new IndexOutOfBoundsException( + "range: "+range+", array size: "+currentLength); + } + } + + public void reverse(){ + int pivotPoint = currentLength/2; + for(int i=0; i 0){ + System.arraycopy(data, (int)range.getEnd()+1, + data, (int)range.getBegin(), numMoved); + } + currentLength-=(int)range.getLength(); + } + public int remove(int offset){ + assertValidOffset(offset); + int oldValue = data[offset]; + + int numMoved = currentLength - offset - 1; + if (numMoved > 0){ + System.arraycopy(data, offset+1, data, offset, numMoved); + } + currentLength--; + return oldValue; + } + /** + * Get the current capacity of the backing + * array. This may be larger than the value + * returned by {@link #getCurrentLength()}. + * Modifying this growable array to extend + * beyond the current capacity will require + * the backing array to be grown. + * @return the current capacity; + * will always be >=0; + */ + public int getCurrentCapacity(){ + return data.length; + } + + private void ensureCapacity(int minCapacity) { + int oldCapacity = data.length; + if (minCapacity > oldCapacity) { + //algorithm borrowed from ArrayList + int newCapacity = (oldCapacity * 3)/2 + 1; + if (newCapacity < minCapacity){ + newCapacity = minCapacity; + } + // minCapacity is usually close to size, so this is a win: + data = Arrays.copyOf(data, newCapacity); + } + } + + public int[] toArray(){ + return Arrays.copyOf(data,currentLength); + } + + + /** + * Searches the current values in this growable array + * using the binary search algorithm as implemented + * by {@link Arrays#binarySearch(int[], int)}. + * The array must be sorted (as + * by the {@link #sort()} method) prior to making this call. If it + * is not sorted, the results are undefined. If the array contains + * multiple elements with the specified value, there is no guarantee which + * one will be found. + * + * @param key the value to be searched for. + * @return index of the search key, if it is contained in the array; + * otherwise, (-(insertion point) - 1). The + * insertion point is defined as the point at which the + * key would be inserted into the array: the index of the first + * element greater than the key, or a.length if all + * elements in the array are less than the specified key. Note + * that this guarantees that the return value will be >= 0 if + * and only if the key is found. + * @throws IllegalArgumentException + * if {@code fromIndex > toIndex} + * @throws ArrayIndexOutOfBoundsException + * if {@code fromIndex < 0 or toIndex > a.length} + *@see Arrays#binarySearch(byte[], byte) + */ + public int binarySearch(int key){ + return Arrays.binarySearch(data, 0, currentLength, key); + } + /** + * Remove the given value from this + * sorted array. This method + * assumes that the values in the backing + * array have been previously sorted. + * If this sorted array contains several + * indexes with this value + * then only one will be removed + * and it is undefined which one will + * actually be removed. + * Calling this method on an unsorted + * backing array may not remove the value + * correctly. + * @param value the value to remove + * @return {@code true} if the value + * was found and removed; {@code false} + * if the value does not exist in the + * sorted backing array. + */ + public boolean sortedRemove(int value){ + int index = binarySearch(value); + + if (index >= 0) { + remove(index); + return true; + } + return false; + } + /** + * Insert the given value into the + * sorted backing array. + * Calling this method on an unsorted + * backing array may not insert the value + * correctly. + * @param value the value to insert. + * @return the index that this value + * was inserted into. + */ + public int sortedInsert(int value){ + int index = binarySearch(value); + if(index <0){ + //not found + //value returned is (-insertion point) -1) + index = -index -1; + } + insert(index, value); + return index; + } + /** + * Insert the given sorted array of values into the + * sorted backing array. This should produce identical + * results + * to iterating over the array and calling + * {@link #sortedInsert(int)} on each element, + * but is hopefully more efficient. + * + * Calling this method on an unsorted + * backing array may not insert the value + * correctly. + * @param values the values to insert. + */ + public void sortedInsert(int[] values){ + if(values.length==0){ + //no-op + return; + } + if(currentLength ==0){ + //we have 0 length + //act just like append + append(values); + return; + } + int[] newData = new int[data.length + values.length]; + int newCurrentLength = currentLength + values.length; + + int ourDataIndex=0, otherDataIndex=0; + + int ourNextValue = data[0]; + int otherNextValue = values[0]; + int i=0; + for(; ourDataIndex iterator() { + return intIterator(); + } + /** + * Create a new primitive int iterator. + * @return + * @since 6.0 + */ + public OfInt intIterator() { + return PrimitiveArrayIterators.create(data, currentLength); + } + /** + * Get the number of values + * in this array that currently + * have the given value. + * @param value the value to look for. + * @return the number of cells with + * the value; will always be >= 0. + */ + public int getCount(int value){ + int count=0; + for(int i=0; i toBoxedList() { + if(currentLength ==0){ + //return new list to make it mutable + return new ArrayList<>(); + } + return ArrayUtil.asList(toArray()); + } + + /** + * Iterate over each element in the list and call the given consumer + * which captures the offset and the value. + * @param consumer the consumer of each element; can not be null. + * @param the Throwable that might be thrown by the consumer. + * @throws E the Throwable from the consumer. + * + * + * + * @throws NullPointerException if consumer is null. + */ + public void forEachIndexed(ThrowingIntIndexedIntConsumer consumer) throws E{ + Objects.requireNonNull(consumer); + for(int i=0; i< currentLength; i++){ + consumer.accept(i, data[i]); + } + } + + /** + * Iterate over the elements in the given range of this array and call the given consumer + * which captures the offset and the value. + * @param consumer the consumer of each element; can not be null. + * @param the Throwable that might be thrown by the consumer. + * @throws E the Throwable from the consumer. + * + * + */ + public void forEachIndexed(Range range, ThrowingIntIndexedIntConsumer consumer) throws E{ + int end = (int) Math.min(currentLength, range.getEnd()+1); + for(int i=(int) range.getBegin(); i< end; i++){ + consumer.accept(i, data[i]); + } + } +}