com.github.tommyettinger.ds.EnhancedCollection 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) 2024-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.Appender;
import java.util.Collection;
import java.util.Iterator;
/**
* Augments {@link Collection} with default methods that can usually use the same implementation across subtypes.
* This generally brings Object-based collections to parity with the default methods provided by the various
* {@link PrimitiveCollection} types.
*
* @param the type of items in this collection
*/
public interface EnhancedCollection extends Collection {
/**
* Adds all parameters using {@link #add(Object)} for each one. Returns true if the set was modified.
* @param item0 a T item
* @param item1 a T item
* @return true if this modified the set
*/
default boolean add(T item0, T item1) {
return add(item0) | add(item1);
}
/**
* Adds all parameters using {@link #add(Object)} for each one. Returns true if the set was modified.
* @param item0 a T item
* @param item1 a T item
* @param item2 a T item
* @return true if this modified the set
*/
default boolean add(T item0, T item1, T item2) {
return add(item0) | add(item1) | add(item2);
}
/**
* Adds all parameters using {@link #add(Object)} for each one. Returns true if the set was modified.
* @param item0 a T item
* @param item1 a T item
* @param item2 a T item
* @param item3 a T item
* @return true if this modified the set
*/
default boolean add(T item0, T item1, T item2, T item3) {
return add(item0) | add(item1) | add(item2) | add(item3);
}
default boolean addAll (Iterator extends T> it) {
int oldSize = size();
while (it.hasNext()) {
add(it.next());
}
return oldSize != size();
}
/**
* Removes from this collection all occurrences of any elements contained in the specified Iterator.
*
* @param it an Iterator of items to remove fully
* @return true if this collection was modified.
*/
default boolean removeAll (Iterator extends T> it) {
Iterator me;
int originalSize = size();
while (it.hasNext()) {
T item = it.next();
me = iterator();
while (me.hasNext()) {
if (me.next() == item) {
me.remove();
}
}
}
return originalSize != size();
}
default boolean removeAll (Object[] array) {
return removeAll(array, 0, array.length);
}
default boolean removeAll (Object[] array, int offset, int length) {
Iterator me;
int originalSize = size();
for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
Object item = array[i];
me = iterator();
while (me.hasNext()) {
if (me.next() == 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 an Iterable of any items to remove one-by-one, such as an ObjectList or ObjectSet
* @return true if this collection was modified.
*/
default boolean removeEach (Iterable> other) {
return removeEach(other.iterator());
}
/**
* 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 it an Iterable of any items to remove one-by-one, such as an ObjectList or ObjectSet
* @return true if this collection was modified.
*/
default boolean removeEach (Iterator> it) {
boolean changed = false;
while (it.hasNext()) {
changed |= remove(it.next());
}
return changed;
}
default boolean removeEach (Object[] array) {
return removeEach(array, 0, array.length);
}
default boolean removeEach (Object[] 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 (Iterator> it) {
while (it.hasNext()) {
if(!contains(it.next())) return false;
}
return true;
}
default boolean containsAll (Object[] array) {
return containsAll(array, 0, array.length);
}
default boolean containsAll (Object[] 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;
}
/**
* Like {@link Collection#containsAll(Collection)}, but returns true immediately if any item in the given Iterable
* {@code other} is present in this EnhancedCollection.
* @param other a Collection or other Iterable of any type to look through
* @return true if any items from the Iterable are present in this EnhancedCollection
*/
default boolean containsAny (Iterable> other) {
return containsAny(other.iterator());
}
/**
* Like {@link Collection#containsAll(Collection)}, but returns true immediately if any item in the given Iterator
* {@code it} is present in this EnhancedCollection.
* @param it an Iterator of any type to look through
* @return true if any items from the Iterator are present in this EnhancedCollection
*/
default boolean containsAny (Iterator> it) {
while (it.hasNext()) {
if(contains(it.next())) return true;
}
return false;
}
default boolean containsAny (Object[] array) {
return containsAny(array, 0, array.length);
}
/**
* Like {@link Collection#containsAll(Collection)}, but returns true immediately if any item in the given {@code array}
* is present in this EnhancedCollection.
* @param array an array to look through; will not be modified
* @param offset the first index in array to check
* @param length how many items in array to check
* @return true if any items from array are present in this EnhancedCollection
*/
default boolean containsAny (Object[] 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;
}
/**
* Attempts to get the first item in this EnhancedCollection, 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 EnhancedCollection, as produced by {@link #iterator()}
* @throws IllegalStateException if this is empty
*/
default T first () {
Iterator it = iterator();
if (it.hasNext())
return it.next();
throw new IllegalStateException("Can't get the first() item of an empty EnhancedCollection.");
}
// 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 EnhancedCollection, but uses the given {@link Appender}
* 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 T, and returns the modified StringBuilder
* @return a new String representing this EnhancedCollection
*/
default String toString (String separator, boolean brackets,
Appender 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 EnhancedCollection, but uses the given {@link Appender}
* 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 T, and returns the modified StringBuilder
* @return {@code sb}, with the appended items of this EnhancedCollection
*/
default StringBuilder appendTo (StringBuilder sb, String separator, boolean brackets, Appender appender) {
if (isEmpty()) {return brackets ? sb.append("[]") : sb;}
if (brackets) {sb.append('[');}
Iterator it = iterator();
while (it.hasNext()) {
T next = it.next();
if(next == this) sb.append("(this)");
else appender.apply(sb, next);
if(it.hasNext()) sb.append(separator);
}
if (brackets) {sb.append(']');}
return sb;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy