
com.github.tommyettinger.ds.PrimitiveCollection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jdkgdxds Show documentation
Show all versions of jdkgdxds Show documentation
Making libGDX's data structures implement JDK interfaces.
The newest version!
/*
* Copyright (c) 2022-2025 See AUTHORS file.
*
* 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 com.github.tommyettinger.ds;
import com.github.tommyettinger.ds.support.util.BooleanAppender;
import com.github.tommyettinger.ds.support.util.ByteAppender;
import com.github.tommyettinger.ds.support.util.CharAppender;
import com.github.tommyettinger.ds.support.util.DoubleAppender;
import com.github.tommyettinger.ds.support.util.DoubleIterator;
import com.github.tommyettinger.ds.support.util.FloatAppender;
import com.github.tommyettinger.ds.support.util.IntAppender;
import com.github.tommyettinger.ds.support.util.IntIterator;
import com.github.tommyettinger.ds.support.util.LongAppender;
import com.github.tommyettinger.ds.support.util.LongIterator;
import com.github.tommyettinger.ds.support.util.ShortAppender;
import com.github.tommyettinger.function.BooleanConsumer;
import com.github.tommyettinger.function.BooleanPredicate;
import com.github.tommyettinger.function.ByteConsumer;
import com.github.tommyettinger.function.BytePredicate;
import com.github.tommyettinger.function.CharConsumer;
import com.github.tommyettinger.function.CharPredicate;
import com.github.tommyettinger.function.FloatConsumer;
import com.github.tommyettinger.function.FloatPredicate;
import com.github.tommyettinger.function.ShortConsumer;
import com.github.tommyettinger.function.ShortPredicate;
import com.github.tommyettinger.ds.support.util.BooleanIterator;
import com.github.tommyettinger.ds.support.util.ByteIterator;
import com.github.tommyettinger.ds.support.util.CharIterator;
import com.github.tommyettinger.ds.support.util.FloatIterator;
import com.github.tommyettinger.ds.support.util.ShortIterator;
import java.util.Iterator;
import com.github.tommyettinger.function.DoubleConsumer;
import com.github.tommyettinger.function.DoublePredicate;
import com.github.tommyettinger.function.IntConsumer;
import com.github.tommyettinger.function.IntPredicate;
import com.github.tommyettinger.function.LongConsumer;
import com.github.tommyettinger.function.LongPredicate;
/**
* Analogous to {@link java.util.Collection} but for a primitive type, this is technically built around
* {@link Iterator}, but should almost always use a primitive-specialized iterator such as
* {@link FloatIterator} instead of the generic {@link Iterator}. This is not necessarily a modifiable
* collection. The nested interfaces define most of the actually useful operations, and you will probably
* never use PrimitiveCollection directly.
*/
public interface PrimitiveCollection {
int size ();
default boolean isEmpty () {
return size() == 0;
}
default boolean notEmpty () {
return size() != 0;
}
Iterator iterator ();
void clear ();
@Override
int hashCode ();
@Override
boolean equals (Object other);
/**
* A PrimitiveCollection with unboxed {@code int} items.
*/
interface OfInt extends PrimitiveCollection {
boolean add (int item);
boolean remove (int item);
boolean contains (int item);
default boolean addAll (OfInt other) {
return addAll(other.iterator());
}
default boolean addAll (IntIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextInt());
}
return changed;
}
default boolean addAll (int[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (int[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of int items to remove fully, such as an IntList or an IntSet
* @return true if this collection was modified.
*/
default boolean removeAll (OfInt other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified IntIterator.
*
* @param it a IntIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (IntIterator it) {
IntIterator me;
int originalSize = size();
while (it.hasNext()) {
int item = it.nextInt();
me = iterator();
while (me.hasNext()) {
if (me.nextInt() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (int[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (int[] array, int offset, int length) {
IntIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
int item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextInt() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of int items to remove one-by-one, such as an IntList or an IntSet
* @return true if this collection was modified.
*/
default boolean removeEach (OfInt other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified IntIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a IntIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (IntIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextInt());
}
return changed;
}
default boolean removeEach (int[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (int[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfInt other) {
return containsAll(other.iterator());
}
default boolean containsAll (IntIterator it) {
while (it.hasNext()) {
if(!contains(it.nextInt())) return false;
}
return true;
}
default boolean containsAll (int[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (int[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfInt other) {
return containsAny(other.iterator());
}
default boolean containsAny (IntIterator it) {
while (it.hasNext()) {
if(contains(it.nextInt())) return true;
}
return false;
}
default boolean containsAny (int[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (int[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (IntPredicate filter) {
boolean removed = false;
final IntIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextInt())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfInt other) {
boolean changed = false;
IntIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextInt())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
IntIterator iterator ();
/**
* Allocates a new int array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new int array
*/
default int[] toArray () {
final int sz = size();
int[] receiver = new int[sz];
IntIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextInt();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* int array with {@link #size()} items and returns that.
*
* @param receiver an int array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new int array otherwise
*/
default int[] toArray (int[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new int[sz];
IntIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextInt();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfInt}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (IntConsumer action) {
IntIterator it = iterator();
while (it.hasNext())
action.accept(it.nextInt());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default int first () {
IntIterator it = iterator();
if (it.hasNext())
return it.nextInt();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
/**
* Compares this PrimitiveCollection.OfInt with a PrimitiveSet.SetOfInt by checking their identity,
* their types (both must implement PrimitiveCollection.OfInt, and other must implement PrimitiveSet.SetOfInt),
* and their sizes, before checking if other contains each item in this PrimitiveCollection.OfInt, in any order
* or quantity. This is most useful for the key "set" or value collection in a primitive-backed map, since
* quantity doesn't matter for keys and order doesn't matter for either. Many implementations may need to reset
* the iterator on this PrimitiveCollection.OfInt, but that isn't necessary for {@code other}.
*
* This is not meant for general object equality, but instead for equality following Set semantics. Classes that
* implement PrimitiveCollection that are not Set-like should usually not use this.
*
* @param other another Object that should be a PrimitiveSet.SetOfInt
* @return true if other is a PrimitiveSet.SetOfInt with exactly the same items, false otherwise
*/
default boolean equalContents (Object other) {
if(this == other) return true;
if(!(other instanceof PrimitiveSet.SetOfInt)) return false;
PrimitiveSet.SetOfInt o = (PrimitiveSet.SetOfInt) other;
if(size() != o.size()) return false;
IntIterator it = iterator();
while (it.hasNext()) {
if(!o.contains(it.nextInt())) return false;
}
return true;
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link IntAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and an int, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
IntAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link IntAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and an int, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, IntAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
IntIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextInt());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
/**
* A PrimitiveCollection with unboxed {@code long} items.
*/
interface OfLong extends PrimitiveCollection {
boolean add (long item);
boolean remove (long item);
boolean contains (long item);
default boolean addAll (OfLong other) {
return addAll(other.iterator());
}
default boolean addAll (LongIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextLong());
}
return changed;
}
default boolean addAll (long[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (long[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of long items to remove fully, such as a LongList or a LongSet
* @return true if this collection was modified.
*/
default boolean removeAll (OfLong other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified LongIterator.
*
* @param it a LongIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (LongIterator it) {
LongIterator me;
int originalSize = size();
while (it.hasNext()) {
long item = it.nextLong();
me = iterator();
while (me.hasNext()) {
if (me.nextLong() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (long[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (long[] array, int offset, int length) {
LongIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
long item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextLong() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of long items to remove one-by-one, such as a LongList or a LongSet
* @return true if this collection was modified.
*/
default boolean removeEach (OfLong other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified LongIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a LongIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (LongIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextLong());
}
return changed;
}
default boolean removeEach (long[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (long[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfLong other) {
return containsAll(other.iterator());
}
default boolean containsAll (LongIterator it) {
while (it.hasNext()) {
if(!contains(it.nextLong())) return false;
}
return true;
}
default boolean containsAll (long[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (long[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfLong other) {
return containsAny(other.iterator());
}
default boolean containsAny (LongIterator it) {
while (it.hasNext()) {
if(contains(it.nextLong())) return true;
}
return false;
}
default boolean containsAny (long[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (long[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (LongPredicate filter) {
boolean removed = false;
final LongIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextLong())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfLong other) {
boolean changed = false;
LongIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextLong())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
LongIterator iterator ();
/**
* Allocates a new long array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new long array
*/
default long[] toArray () {
final int sz = size();
long[] receiver = new long[sz];
LongIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextLong();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* long array with {@link #size()} items and returns that.
*
* @param receiver a long array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new long array otherwise
*/
default long[] toArray (long[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new long[sz];
LongIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextLong();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfLong}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (LongConsumer action) {
LongIterator it = iterator();
while (it.hasNext())
action.accept(it.nextLong());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default long first () {
LongIterator it = iterator();
if (it.hasNext())
return it.nextLong();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
/**
* Compares this PrimitiveCollection.OfLong with a PrimitiveSet.SetOfLong by checking their identity,
* their types (both must implement PrimitiveCollection.OfLong, and other must implement PrimitiveSet.SetOfLong),
* and their sizes, before checking if other contains each item in this PrimitiveCollection.OfLong, in any order
* or quantity. This is most useful for the key "set" or value collection in a primitive-backed map, since
* quantity doesn't matter for keys and order doesn't matter for either. Many implementations may need to reset
* the iterator on this PrimitiveCollection.OfLong, but that isn't necessary for {@code other}.
*
* This is not meant for general object equality, but instead for equality following Set semantics. Classes that
* implement PrimitiveCollection that are not Set-like should usually not use this.
*
* @param other another Object that should be a PrimitiveSet.SetOfLong
* @return true if other is a PrimitiveSet.SetOfLong with exactly the same items, false otherwise
*/
default boolean equalContents (Object other) {
if(this == other) return true;
if(!(other instanceof PrimitiveSet.SetOfLong)) return false;
PrimitiveSet.SetOfLong o = (PrimitiveSet.SetOfLong) other;
if(size() != o.size()) return false;
LongIterator it = iterator();
while (it.hasNext()) {
if(!o.contains(it.nextLong())) return false;
}
return true;
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link LongAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a long, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
LongAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link LongAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a long, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, LongAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
LongIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextLong());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
/**
* A PrimitiveCollection with unboxed {@code float} items.
*/
interface OfFloat extends PrimitiveCollection {
boolean add (float item);
boolean remove (float item);
boolean contains (float item);
default boolean addAll (OfFloat other) {
return addAll(other.iterator());
}
default boolean addAll (FloatIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextFloat());
}
return changed;
}
default boolean addAll (float[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (float[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of float items to remove fully, such as a FloatList or a FloatDeque
* @return true if this collection was modified.
*/
default boolean removeAll (OfFloat other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified FloatIterator.
*
* @param it a FloatIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (FloatIterator it) {
FloatIterator me;
int originalSize = size();
while (it.hasNext()) {
float item = it.nextFloat();
me = iterator();
while (me.hasNext()) {
if (me.nextFloat() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (float[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (float[] array, int offset, int length) {
FloatIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
float item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextFloat() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of float items to remove one-by-one, such as a FloatList or a FloatDeque
* @return true if this collection was modified.
*/
default boolean removeEach (OfFloat other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified FloatIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a FloatIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (FloatIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextFloat());
}
return changed;
}
default boolean removeEach (float[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (float[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfFloat other) {
return containsAll(other.iterator());
}
default boolean containsAll (FloatIterator it) {
while (it.hasNext()) {
if(!contains(it.nextFloat())) return false;
}
return true;
}
default boolean containsAll (float[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (float[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfFloat other) {
return containsAny(other.iterator());
}
default boolean containsAny (FloatIterator it) {
while (it.hasNext()) {
if(contains(it.nextFloat())) return true;
}
return false;
}
default boolean containsAny (float[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (float[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (FloatPredicate filter) {
boolean removed = false;
final FloatIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextFloat())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfFloat other) {
boolean changed = false;
FloatIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextFloat())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
FloatIterator iterator ();
/**
* Allocates a new float array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new float array
*/
default float[] toArray () {
final int sz = size();
float[] receiver = new float[sz];
FloatIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextFloat();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* float array with {@link #size()} items and returns that.
*
* @param receiver a float array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new float array otherwise
*/
default float[] toArray (float[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new float[sz];
FloatIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextFloat();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfFloat}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (FloatConsumer action) {
FloatIterator it = iterator();
while (it.hasNext())
action.accept(it.nextFloat());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default float first () {
FloatIterator it = iterator();
if (it.hasNext())
return it.nextFloat();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link FloatAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a float, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
FloatAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link FloatAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a float, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, FloatAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
FloatIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextFloat());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
/**
* A PrimitiveCollection with unboxed {@code double} items.
*/
interface OfDouble extends PrimitiveCollection {
boolean add (double item);
boolean remove (double item);
boolean contains (double item);
default boolean addAll (OfDouble other) {
return addAll(other.iterator());
}
default boolean addAll (DoubleIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextDouble());
}
return changed;
}
default boolean addAll (double[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (double[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of double items to remove fully, such as a DoubleList or a DoubleDeque
* @return true if this collection was modified.
*/
default boolean removeAll (OfDouble other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified DoubleIterator.
*
* @param it a DoubleIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (DoubleIterator it) {
DoubleIterator me;
int originalSize = size();
while (it.hasNext()) {
double item = it.nextDouble();
me = iterator();
while (me.hasNext()) {
if (me.nextDouble() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (double[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (double[] array, int offset, int length) {
DoubleIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
double item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextDouble() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of double items to remove one-by-one, such as a DoubleList or a DoubleSet
* @return true if this collection was modified.
*/
default boolean removeEach (OfDouble other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified DoubleIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a DoubleIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (DoubleIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextDouble());
}
return changed;
}
default boolean removeEach (double[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (double[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfDouble other) {
return containsAll(other.iterator());
}
default boolean containsAll (DoubleIterator it) {
while (it.hasNext()) {
if(!contains(it.nextDouble())) return false;
}
return true;
}
default boolean containsAll (double[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (double[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfDouble other) {
return containsAny(other.iterator());
}
default boolean containsAny (DoubleIterator it) {
while (it.hasNext()) {
if(contains(it.nextDouble())) return true;
}
return false;
}
default boolean containsAny (double[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (double[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (DoublePredicate filter) {
boolean removed = false;
final DoubleIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextDouble())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfDouble other) {
boolean changed = false;
DoubleIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextDouble())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
DoubleIterator iterator ();
/**
* Allocates a new double array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new double array
*/
default double[] toArray () {
final int sz = size();
double[] receiver = new double[sz];
DoubleIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextDouble();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* double array with {@link #size()} items and returns that.
*
* @param receiver a double array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new double array otherwise
*/
default double[] toArray (double[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new double[sz];
DoubleIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextDouble();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfDouble}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (DoubleConsumer action) {
DoubleIterator it = iterator();
while (it.hasNext())
action.accept(it.nextDouble());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default double first () {
DoubleIterator it = iterator();
if (it.hasNext())
return it.nextDouble();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link DoubleAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a double, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
DoubleAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link DoubleAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a double, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, DoubleAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
DoubleIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextDouble());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
/**
* A PrimitiveCollection with unboxed {@code short} items.
*/
interface OfShort extends PrimitiveCollection {
boolean add (short item);
boolean remove (short item);
boolean contains (short item);
default boolean addAll (OfShort other) {
return addAll(other.iterator());
}
default boolean addAll (ShortIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextShort());
}
return changed;
}
default boolean addAll (short[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (short[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of short items to remove fully, such as a ShortList or a ShortDeque
* @return true if this collection was modified.
*/
default boolean removeAll (OfShort other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified ShortIterator.
*
* @param it a ShortIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (ShortIterator it) {
ShortIterator me;
int originalSize = size();
while (it.hasNext()) {
short item = it.nextShort();
me = iterator();
while (me.hasNext()) {
if (me.nextShort() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (short[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (short[] array, int offset, int length) {
ShortIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
short item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextShort() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of short items to remove one-by-one, such as a ShortList or a ShortDeque
* @return true if this collection was modified.
*/
default boolean removeEach (OfShort other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified ShortIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a ShortIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (ShortIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextShort());
}
return changed;
}
default boolean removeEach (short[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (short[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfShort other) {
return containsAll(other.iterator());
}
default boolean containsAll (ShortIterator it) {
while (it.hasNext()) {
if(!contains(it.nextShort())) return false;
}
return true;
}
default boolean containsAll (short[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (short[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfShort other) {
return containsAny(other.iterator());
}
default boolean containsAny (ShortIterator it) {
while (it.hasNext()) {
if(contains(it.nextShort())) return true;
}
return false;
}
default boolean containsAny (short[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (short[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (ShortPredicate filter) {
boolean removed = false;
final ShortIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextShort())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfShort other) {
boolean changed = false;
ShortIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextShort())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
ShortIterator iterator ();
/**
* Allocates a new short array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new short array
*/
default short[] toArray () {
final int sz = size();
short[] receiver = new short[sz];
ShortIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextShort();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* short array with {@link #size()} items and returns that.
*
* @param receiver a short array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new short array otherwise
*/
default short[] toArray (short[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new short[sz];
ShortIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextShort();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfShort}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (ShortConsumer action) {
ShortIterator it = iterator();
while (it.hasNext())
action.accept(it.nextShort());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default short first () {
ShortIterator it = iterator();
if (it.hasNext())
return it.nextShort();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link ShortAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a short, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
ShortAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link ShortAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a short, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, ShortAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
ShortIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextShort());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
/**
* A PrimitiveCollection with unboxed {@code byte} items.
*/
interface OfByte extends PrimitiveCollection {
boolean add (byte item);
boolean remove (byte item);
boolean contains (byte item);
default boolean addAll (OfByte other) {
return addAll(other.iterator());
}
default boolean addAll (ByteIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextByte());
}
return changed;
}
default boolean addAll (byte[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (byte[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of byte items to remove fully, such as a ByteList or a ByteDeque
* @return true if this collection was modified.
*/
default boolean removeAll (OfByte other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified ByteIterator.
*
* @param it a ByteIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (ByteIterator it) {
ByteIterator me;
int originalSize = size();
while (it.hasNext()) {
byte item = it.nextByte();
me = iterator();
while (me.hasNext()) {
if (me.nextByte() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (byte[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (byte[] array, int offset, int length) {
ByteIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
byte item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextByte() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of byte items to remove one-by-one, such as a ByteList or a ByteDeque
* @return true if this collection was modified.
*/
default boolean removeEach (OfByte other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified ByteIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a ByteIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (ByteIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextByte());
}
return changed;
}
default boolean removeEach (byte[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (byte[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfByte other) {
return containsAll(other.iterator());
}
default boolean containsAll (ByteIterator it) {
while (it.hasNext()) {
if(!contains(it.nextByte())) return false;
}
return true;
}
default boolean containsAll (byte[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (byte[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfByte other) {
return containsAny(other.iterator());
}
default boolean containsAny (ByteIterator it) {
while (it.hasNext()) {
if(contains(it.nextByte())) return true;
}
return false;
}
default boolean containsAny (byte[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (byte[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (BytePredicate filter) {
boolean removed = false;
final ByteIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextByte())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfByte other) {
boolean changed = false;
ByteIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextByte())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
ByteIterator iterator ();
/**
* Allocates a new byte array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new byte array
*/
default byte[] toArray () {
final int sz = size();
byte[] receiver = new byte[sz];
ByteIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextByte();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* byte array with {@link #size()} items and returns that.
*
* @param receiver a byte array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new byte array otherwise
*/
default byte[] toArray (byte[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new byte[sz];
ByteIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextByte();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfByte}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (ByteConsumer action) {
ByteIterator it = iterator();
while (it.hasNext())
action.accept(it.nextByte());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default byte first () {
ByteIterator it = iterator();
if (it.hasNext())
return it.nextByte();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link ByteAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a byte, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
ByteAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link ByteAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a byte, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, ByteAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
ByteIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextByte());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
/**
* A PrimitiveCollection with unboxed {@code char} items.
*/
interface OfChar extends PrimitiveCollection {
boolean add (char item);
boolean remove (char item);
boolean contains (char item);
default boolean addAll (OfChar other) {
return addAll(other.iterator());
}
default boolean addAll (CharIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextChar());
}
return changed;
}
default boolean addAll (char[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (char[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of char items to remove fully, such as a CharList or a CharDeque
* @return true if this collection was modified.
*/
default boolean removeAll (OfChar other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified CharIterator.
*
* @param it a CharIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (CharIterator it) {
CharIterator me;
int originalSize = size();
while (it.hasNext()) {
char item = it.nextChar();
me = iterator();
while (me.hasNext()) {
if (me.nextChar() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (char[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (char[] array, int offset, int length) {
CharIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
char item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextChar() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of char items to remove one-by-one, such as a CharList or a CharDeque
* @return true if this collection was modified.
*/
default boolean removeEach (OfChar other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified CharIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a CharIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (CharIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextChar());
}
return changed;
}
default boolean removeEach (char[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (char[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfChar other) {
return containsAll(other.iterator());
}
default boolean containsAll (CharIterator it) {
while (it.hasNext()) {
if(!contains(it.nextChar())) return false;
}
return true;
}
default boolean containsAll (char[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (char[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfChar other) {
return containsAny(other.iterator());
}
default boolean containsAny (CharIterator it) {
while (it.hasNext()) {
if(contains(it.nextChar())) return true;
}
return false;
}
default boolean containsAny (char[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (char[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (CharPredicate filter) {
boolean removed = false;
final CharIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextChar())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfChar other) {
boolean changed = false;
CharIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextChar())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
CharIterator iterator ();
/**
* Allocates a new char array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new char array
*/
default char[] toArray () {
final int sz = size();
char[] receiver = new char[sz];
CharIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextChar();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* char array with {@link #size()} items and returns that.
*
* @param receiver a char array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new char array otherwise
*/
default char[] toArray (char[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new char[sz];
CharIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextChar();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfChar}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (CharConsumer action) {
CharIterator it = iterator();
while (it.hasNext())
action.accept(it.nextChar());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default char first () {
CharIterator it = iterator();
if (it.hasNext())
return it.nextChar();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link CharAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a char, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
CharAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link CharAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a char, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, CharAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
CharIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextChar());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
/**
* A PrimitiveCollection with unboxed {@code boolean} items.
*/
interface OfBoolean extends PrimitiveCollection {
boolean add (boolean item);
boolean remove (boolean item);
boolean contains (boolean item);
default boolean addAll (OfBoolean other) {
return addAll(other.iterator());
}
default boolean addAll (BooleanIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= add(it.nextBoolean());
}
return changed;
}
default boolean addAll (boolean[] array) {
return addAll(array, 0, array.length);
}
default boolean addAll (boolean[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= add(array[i]);
}
return changed;
}
/**
* Removes from this collection all occurrences of any elements contained in the specified other collection.
*
* @param other a primitive collection of boolean items to remove fully, such as a BooleanList or a BooleanDeque
* @return true if this collection was modified.
*/
default boolean removeAll (OfBoolean other) {
return removeAll(other.iterator());
}
/**
* Removes from this collection all occurrences of any elements contained in the specified BooleanIterator.
*
* @param it a BooleanIterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (BooleanIterator it) {
BooleanIterator me;
int originalSize = size();
while (it.hasNext()) {
boolean item = it.nextBoolean();
me = iterator();
while (me.hasNext()) {
if (me.nextBoolean() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (boolean[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (boolean[] array, int offset, int length) {
BooleanIterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
boolean item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.nextBoolean() == item) {
me.remove();
}
}
}
return originalSize != size();
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified other collection.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code other}. If {@code other} has the same
* contents as this collection or has additional items, then removing each of {@code other} will clear this.
*
* @param other a primitive collection of boolean items to remove one-by-one, such as a BooleanList or a BooleanDeque
* @return true if this collection was modified.
*/
default boolean removeEach (OfBoolean other) {
return removeEach(other.iterator());
}
/**
* Removes from this collection element-wise occurrences of elements contained in the specified BooleanIterator.
* Note that if a value is present more than once in this collection, only one of those occurrences
* will be removed for each occurrence of that value in {@code it}. If {@code it} has the same
* contents as this collection or has additional items, then removing each of {@code it} will clear this.
*
* @param it a BooleanIterator of items to remove one-by-one
* @return true if this collection was modified.
*/
default boolean removeEach (BooleanIterator it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.nextBoolean());
}
return changed;
}
default boolean removeEach (boolean[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (boolean[] array, int offset, int length) {
boolean changed = false;
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
changed |= remove(array[i]);
}
return changed;
}
default boolean containsAll (OfBoolean other) {
return containsAll(other.iterator());
}
default boolean containsAll (BooleanIterator it) {
while (it.hasNext()) {
if(!contains(it.nextBoolean())) return false;
}
return true;
}
default boolean containsAll (boolean[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (boolean[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(!contains(array[i])) return false;
}
return true;
}
default boolean containsAny (OfBoolean other) {
return containsAny(other.iterator());
}
default boolean containsAny (BooleanIterator it) {
while (it.hasNext()) {
if(contains(it.nextBoolean())) return true;
}
return false;
}
default boolean containsAny (boolean[] array) {
return containsAny(array, 0, array.length);
}
default boolean containsAny (boolean[] array, int offset, int length) {
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
if(contains(array[i])) return true;
}
return false;
}
/**
* Removes all the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
*
* @param filter a predicate which returns {@code true} for elements to be
* removed
* @return {@code true} if any elements were removed
* @throws UnsupportedOperationException if elements cannot be removed
* from this collection. Implementations may throw this exception if a
* matching element cannot be removed or if, in general, removal is not
* supported.
* @implSpec The default implementation traverses all elements of the collection using
* its {@link #iterator()}. Each matching element is removed using
* {@link Iterator#remove()}. If the collection's iterator does not
* support removal then an {@code UnsupportedOperationException} will be
* thrown on the first matching element.
*/
default boolean removeIf (BooleanPredicate filter) {
boolean removed = false;
final BooleanIterator each = iterator();
while (each.hasNext()) {
if (filter.test(each.nextBoolean())) {
each.remove();
removed = true;
}
}
return removed;
}
default boolean retainAll (OfBoolean other) {
boolean changed = false;
BooleanIterator it = iterator();
while (it.hasNext()) {
if (!other.contains(it.nextBoolean())) {
it.remove();
changed = true;
}
}
return changed;
}
@Override
BooleanIterator iterator ();
/**
* Allocates a new boolean array with exactly {@link #size()} items, fills it with the
* contents of this PrimitiveCollection, and returns it.
*
* @return a new boolean array
*/
default boolean[] toArray () {
final int sz = size();
boolean[] receiver = new boolean[sz];
BooleanIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextBoolean();
return receiver;
}
/**
* Fills the given array with the entire contents of this PrimitiveCollection, up to
* {@link #size()} items, or if receiver is not large enough, then this allocates a new
* boolean array with {@link #size()} items and returns that.
*
* @param receiver a boolean array that will be filled with the items from this, if possible
* @return {@code receiver}, if it was modified, or a new boolean array otherwise
*/
default boolean[] toArray (boolean[] receiver) {
final int sz = size();
if (receiver.length < sz)
receiver = new boolean[sz];
BooleanIterator it = iterator();
int i = 0;
while (it.hasNext())
receiver[i++] = it.nextBoolean();
return receiver;
}
/**
* Performs the given action for each element of the {@code PrimitiveCollection.OfBoolean}
* until all elements have been processed or the action throws an
* exception. Actions are performed in the order of iteration, if that
* order is specified. Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
*/
default void forEach (BooleanConsumer action) {
BooleanIterator it = iterator();
while (it.hasNext())
action.accept(it.nextBoolean());
}
/**
* Attempts to get the first item in this PrimitiveCollection, where "first" is only
* defined meaningfully if this type is ordered. Many times, this applies to a class
* that is not ordered, and in those cases it can get an arbitrary item, and that item
* is permitted to be different for different calls to first().
*
* This is useful for cases where you would normally be able to call something like
* {@link java.util.List#get(int)} to get an item, any item, from a collection, but
* whatever class you're using doesn't necessarily provide a get(), first(), peek(),
* or similar method.
*
* The default implementation uses {@link #iterator()}, tries to get the first item,
* or throws an IllegalStateException if this is empty.
*
* @return the first item in this PrimitiveCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default boolean first () {
BooleanIterator it = iterator();
if (it.hasNext())
return it.nextBoolean();
throw new IllegalStateException("Can't get the first() item of an empty PrimitiveCollection.");
}
// STRING CONVERSION
/**
* Delegates to {@link #toString(String, boolean)} with the given entrySeparator and without brackets.
*
* @param entrySeparator how to separate entries, such as {@code ", "}
* @return a new String representing this map
*/
default String toString (String entrySeparator) {
return toString(entrySeparator, false);
}
default String toString (String entrySeparator, boolean brackets) {
return appendTo(new StringBuilder(32), entrySeparator, brackets).toString();
}
/**
* Makes a String from the contents of this PrimitiveCollection, but uses the given {@link BooleanAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a boolean, and returns the modified StringBuilder
* @return a new String representing this PrimitiveCollection
*/
default String toString (String separator, boolean brackets,
BooleanAppender appender){
return appendTo(new StringBuilder(), separator, brackets, appender).toString();
}
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets) {
return appendTo(sb, separator, brackets, StringBuilder::append);
}
/**
* Appends to a StringBuilder from the contents of this PrimitiveCollection, but uses the given {@link BooleanAppender}
* to convert each item to a customizable representation and append them to a StringBuilder. To use
* the default String representation, you can use {@code StringBuilder::append} as an appender.
*
* @param sb a StringBuilder that this can append to
* @param separator how to separate items, such as {@code ", "}
* @param brackets true to wrap the output in square brackets, or false to omit them
* @param appender a function that takes a StringBuilder and a boolean, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this PrimitiveCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, BooleanAppender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
BooleanIterator it = iterator();
while (it.hasNext()) {
appender.apply(sb, it.nextBoolean());
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy