All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tommyettinger.ds.ObjectList Maven / Gradle / Ivy

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.BooleanIterator;
import com.github.tommyettinger.ds.support.sort.ObjectComparators;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Random;

/**
 * A resizable, insertion-ordered list of {@code T} items, typically objects (they can also be arrays).
 * This is a thin wrapper around {@link ArrayList} to implement {@link Ordered} and do some of
 * what libGDX's Array class does. Because this is a generic class and arrays do not interact
 * well with generics, ObjectList does not permit access to a {@code T[]} of items like Array
 * does; you can use {@link #toArray(Object[])} or (if you can use Java 11)
 * {@code toArray(IntFunction)} to make a new array of T from the contents of an ArrayList.
 * The second of these toArray methods is newer; You can use it with code like
 * {@code ObjectList myList = new ObjectList<>(); String[] s = myList.toArray(String::new);}.
 *
 * @author Tommy Ettinger
 * @see ObjectBag ObjectBag is an unordered variant on ObjectList.
 */
public class ObjectList extends ArrayList implements Ordered, EnhancedCollection {

	@Nullable protected transient ObjectListIterator iterator1;
	@Nullable protected transient ObjectListIterator iterator2;

	/**
	 * Returns true if this implementation retains order, which it does.
	 * @return true
	 */
	public boolean keepsOrder () {
		return true;
	}

	/**
	 * Constructs an empty list with the specified initial capacity.
	 *
	 * @param initialCapacity the initial capacity of the list
	 * @throws IllegalArgumentException if the specified initial capacity
	 *                                  is negative
	 */
	public ObjectList (int initialCapacity) {
		super(initialCapacity);
	}

	/**
	 * Constructs an empty list with the specified initial capacity.
	 *
	 * @param ordered         ignored; use an {@link ObjectBag} for an unordered list
	 * @param initialCapacity the initial capacity of the list
	 * @throws IllegalArgumentException if the specified initial capacity
	 *                                  is negative
	 * @deprecated This is equivalent to {@link #ObjectList(int)}; make an {@link ObjectBag} for an unordered list
	 */
	@Deprecated
	public ObjectList (boolean ordered, int initialCapacity) {
		super(initialCapacity);
	}

	/**
	 * Constructs an empty list with an initial capacity of 10.
	 */
	public ObjectList () {
		super();
	}

	/**
	 * Constructs a list containing the elements of the specified
	 * collection, in the order they are returned by the collection's
	 * iterator.
	 *
	 * @param c the collection whose elements are to be placed into this list
	 * @throws NullPointerException if the specified collection is null
	 */
	public ObjectList (Collection c) {
		super(c);
	}

	/**
	 * Constructs a list containing the elements of the specified
	 * collection, in the order they are returned by the collection's
	 * iterator.
	 *
	 * @param ordered ignored; use an {@link ObjectBag} for an unordered list
	 * @param c       the collection whose elements are to be placed into this list
	 * @throws NullPointerException if the specified collection is null
	 * @deprecated This is equivalent to {@link #ObjectList(Collection)}; make an {@link ObjectBag} for an unordered list
	 */
	@Deprecated
	public ObjectList (boolean ordered, Collection c) {
		super(c);
	}

	/**
	 * Creates a new instance containing the items in the specified iterator.
	 *
	 * @param coll an iterator that will have its remaining contents added to this
	 */
	public ObjectList (Iterator coll) {
		this();
		addAll(coll);
	}

	public ObjectList (T[] a) {
		super(a.length);
		Collections.addAll(this, a);
	}

	public ObjectList (T[] a, int offset, int count) {
		super(a.length);
		for (int i = offset, n = Math.min(offset + count, a.length); i < n; i++) {
			add(a[i]);
		}
	}

	/**
	 * Creates a new list by copying {@code count} items from the given Ordered, starting at {@code offset} in that Ordered,
	 * into this.
	 *
	 * @param other  another Ordered of the same type
	 * @param offset the first index in other's ordering to draw an item from
	 * @param count  how many items to copy from other
	 */
	public ObjectList (Ordered other, int offset, int count) {
		super(count);
		addAll(0, other, offset, count);
	}

	@Override
	public void add (int index, @Nullable T element) {
		super.add(index, element);
	}

	/**
	 * This is an alias for {@link #add(int, Object)} to improve compatibility with primitive lists.
	 *
	 * @param index   index at which the specified element is to be inserted
	 * @param element element to be inserted
	 */
	public void insert (int index, @Nullable T element) {
		super.add(index, element);
	}

	@Override
	@Nullable
	public T remove (int index) {
		return super.remove(index);
	}

	/**
	 * This is an alias for {@link #remove(int)} to make the API the same for primitive lists.
	 *
	 * @param index must be non-negative and less than {@link #size()}
	 * @return the previously-held item at the given index
	 */
	@Nullable
	public T removeAt (int index) {
		return super.remove(index);
	}

	/**
	 * Removes the items between the specified start index, inclusive, and end index, exclusive.
	 * Note that this takes different arguments than some other range-related methods; this needs
	 * a start index and an end index, rather than a count of items. This matches the behavior in
	 * the JDK collections. This is also different from removeRange() in the libGDX Array class
	 * because it is exclusive on end, instead of how Array is inclusive on end.
	 *
	 * @param start the first index to remove, inclusive
	 * @param end   the last index (after what should be removed), exclusive
	 */
	@Override
	public void removeRange (int start, int end) {
		super.removeRange(start, end);
	}

	/**
	 * Exactly like {@link #removeAll(Collection)}, but takes an array instead of a Collection.
	 * @see #removeAll(Collection)
	 * @param other array containing elements to be removed from this list
	 * @return {@code true} if this list changed as a result of the call
	 */
	public boolean removeAll (Object[] other) {
		return removeAll(other, 0, other.length);
	}
	/**
	 * Like {@link #removeAll(Object[])}, but only uses at most {@code length} items from {@code array}, starting at {@code offset}.
	 * @see #removeAll(Object[])
	 * @param array the elements to be removed from this list
	 * @param offset the index of the first item in array to remove
	 * @param length how many items, at most, to get from array and remove from this
	 * @return {@code true} if this list changed as a result of the call
	 */
	public boolean removeAll (Object[] array, int offset, int length) {
		ObjectListIterator me = iterator();
		int originalSize = size();
		for (int i = offset, n = 0; n < length && i < array.length; i++, n++) {
			Object item = array[i];
			me.reset();
			while (me.hasNext()) {
				if (Objects.equals(me.next(), item)) {
					me.remove();
				}
			}
		}
		return originalSize != size();
	}

	/**
	 * Removes from this ObjectList element-wise occurrences of elements contained in the specified Iterable.
	 * Note that if a value is present more than once in this ObjectList, 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 ObjectList or has additional items, then removing each of {@code other} will clear this.
	 * 
* This matches the behavior of the libGDX {@code Array.removeAll(Array)} method in libGDX 1.10.0 and earlier. * The method {@link #removeAll(Collection)} here matches the behavior of the JDK * {@link List#removeAll(Collection)} method. * * @param other an Iterable of T items to remove one-by-one, such as another ObjectList or an ObjectSet * @return true if this list was modified. */ public boolean removeEach (Iterable other) { boolean changed = false; for(Object item : other) { changed |= remove(item); } return changed; } /** * Exactly like {@link #removeEach(Iterable)}, but takes an array instead of a Collection. * @see #removeEach(Iterable) * @param array array containing elements to be removed from this list * @return {@code true} if this list changed as a result of the call */ public boolean removeEach (Object[] array) { return removeEach(array, 0, array.length); } /** * Like {@link #removeEach(Object[])}, but only uses at most {@code length} items from {@code array}, starting at {@code offset}. * @see #removeEach(Object[]) * @param array the elements to be removed from this list * @param offset the index of the first item in array to remove * @param length how many items, at most, to get from array and remove from this * @return {@code true} if this list changed as a result of the call */ public 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; } /** * Adds each item in the array {@code a} to this ObjectList, appending to the end. * * @param a a non-null array of {@code T} * @return true if this is modified by this call, as {@link #addAll(Collection)} does */ public boolean addAll (T[] a) { return Collections.addAll(this, a); } /** * Adds each item in the array {@code a} to this ObjectList, inserting starting at {@code insertionIndex}. * * @param insertionIndex where to insert into this ObjectList * @param a a non-null array of {@code T} * @return true if this is modified by this call, as {@link #addAll(Collection)} does */ public boolean addAll (int insertionIndex, T[] a) { return addAll(insertionIndex, a, 0, a.length); } /** * Adds up to {@code count} items, starting from {@code offset}, in the array {@code a} to this ObjectList, appending to the end. * * @param a a non-null array of {@code T} * @param offset the first index in {@code a} to use * @param count how many indices in {@code a} to use * @return true if this is modified by this call, as {@link #addAll(Collection)} does */ public boolean addAll (T[] a, int offset, int count) { if(offset < 0) throw new IndexOutOfBoundsException("offset cannot be negative."); int n = Math.min(offset + count, a.length); for (int i = offset; i < n; i++) { add(a[i]); } return offset < n; } /** * Inserts the specified number of items at the specified index. The new items will have values equal to the values at those * indices before the insertion, and the previous values will be pushed to after the duplicated range. * @param index the first index to duplicate * @param count how many items to duplicate */ public boolean duplicateRange (int index, int count) { if (index + count >= size()) {throw new IllegalStateException("Sum of index and count is too large: " + (index + count) + " must not be >= " + size());} addAll(index, subList(index, index + count)); return count > 0; } /** * Exactly like {@link #containsAll(Collection)}, but takes an array instead of a Collection. * @see #containsAll(Collection) * @param array array to be checked for containment in this collection * @return {@code true} if this list contains all the elements in the specified array */ public boolean containsAll (Object[] array) { for (Object o : array) { if (!contains(o)) return false; } return true; } /** * Like {@link #containsAll(Object[])}, but only uses at most {@code length} items from {@code array}, starting at {@code offset}. * @see #containsAll(Object[]) * @param array array to be checked for containment in this collection * @param offset the index of the first item in array to check * @param length how many items, at most, to check from array * @return {@code true} if this collection contains all the elements in the specified range of array */ public 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; } /** * Returns true if this ObjectList contains any of the specified values. * * @param values may contain nulls, but must not be null itself * @return true if this ObjectList contains any of the items in {@code values}, false otherwise */ public boolean containsAny (Iterable values) { for (Object v : values) { if (contains(v)) {return true;} } return false; } /** * Returns true if this ObjectList contains any of the specified values. * * @param values may contain nulls, but must not be null itself * @return true if this ObjectList contains any of the items in {@code values}, false otherwise */ public boolean containsAny (Object[] values) { for (Object v : values) { if (contains(v)) {return true;} } return false; } /** * Returns true if this ObjectList contains any items from the specified range of values. * * @param values may contain nulls, but must not be null itself * @param offset the index to start checking in values * @param length how many items to check from values * @return true if this ObjectList contains any of the items in the given range of {@code values}, false otherwise */ public boolean containsAny (Object[] values, int offset, int length) { for (int i = offset, n = 0; n < length && i < values.length; i++, n++) { if (contains(values[i])) {return true;} } return false; } /** * Adds up to {@code count} items, starting from {@code offset}, in the array {@code a} to this ObjectList, * inserting starting at {@code insertionIndex}. * * @param insertionIndex where to insert into this ObjectList * @param a a non-null array of {@code T} * @param offset the first index in {@code a} to use * @param count how many indices in {@code a} to use * @return true if this is modified by this call, as {@link #addAll(Collection)} does */ public boolean addAll (int insertionIndex, T[] a, int offset, int count) { boolean changed = false; int end = Math.min(offset + count, a.length); ensureCapacity(end - offset); for (int i = offset; i < end; i++) { add(insertionIndex++, a[i]); changed = true; } return changed; } /** * Adds up to {@code count} items, starting from {@code offset}, in the Ordered {@code other} to this list, * inserting at the end of the iteration order. * * @param other a non-null {@link Ordered} of {@code T} * @param offset the first index in {@code other} to use * @param count how many indices in {@code other} to use * @return true if this is modified by this call, as {@link #addAll(Collection)} does */ public boolean addAll (Ordered other, int offset, int count) { return addAll(size(), other, offset, count); } /** * Adds up to {@code count} items, starting from {@code offset}, in the Ordered {@code other} to this list, * inserting starting at {@code insertionIndex} in the iteration order. * * @param insertionIndex where to insert into the iteration order * @param other a non-null {@link Ordered} of {@code T} * @param offset the first index in {@code other} to use * @param count how many indices in {@code other} to use * @return true if this is modified by this call, as {@link #addAll(Collection)} does */ public boolean addAll (int insertionIndex, Ordered other, int offset, int count) { boolean changed = false; int end = Math.min(offset + count, other.size()); ensureCapacity(end - offset); for (int i = offset; i < end; i++) { add(insertionIndex++, other.order().get(i)); changed = true; } return changed; } /** * Removes and returns the last item. */ @Nullable public T pop () { int n = size(); if (n == 0) {throw new IllegalStateException("ObjectList is empty.");} return remove(n - 1); } /** * Returns the last item. */ @Nullable public T peek () { int n = size(); if (n == 0) {throw new IllegalStateException("ObjectList is empty.");} return get(n - 1); } /** * Returns the first item. */ @Nullable public T first () { if (size() == 0) {throw new IllegalStateException("ObjectList is empty.");} return get(0); } /** * Returns true if the array has one or more items. */ public boolean notEmpty () { return size() != 0; } /** * Increases the size of the backing array to accommodate the specified number of additional items. Useful before adding many * items to avoid multiple backing array resizes. Note that this has different behavior from {@link ArrayList#ensureCapacity(int)}; * ArrayList's version specifies a minimum capacity (which can result in no change if the capacity is currently larger than that * minimum), whereas this version specifies additional capacity (which always increases capacity if {@code additionalCapacity} is * non-negative). The behavior here matches the primitive-backed lists like {@link IntList}, as well as libGDX Array classes. * * @param additionalCapacity how much room to add to the capacity; this is measured in the number of items this can store */ @Override public void ensureCapacity (int additionalCapacity) { super.ensureCapacity(size() + additionalCapacity); } /** * Uses == for comparison of each item. */ public boolean equalsIdentity (Object object) { if (object == this) {return true;} if (!(object instanceof List)) {return false;} List list = (List)object; int n = size(); if (n != list.size()) {return false;} for (int i = 0; i < n; i++) {if (get(i) != list.get(i)) {return false;}} return true; } @Override public boolean equals (Object o) { if (o == this) return true; return super.equals(o); } @Override public int hashCode () { return super.hashCode(); } @Override public String toString () { return toString(", ", true); } public StringBuilder appendTo (StringBuilder builder, String separator) { int n = size(); if (n == 0) {return builder;} builder.append(get(0)); for (int i = 1; i < n; i++) { builder.append(separator); builder.append(get(i)); } return builder; } /** * Returns a list iterator over the elements in this list (in proper * sequence), starting at the specified position in the list. * The specified index indicates the first element that would be * returned by an initial call to {@link ListIterator#next next}. * An initial call to {@link ListIterator#previous previous} would * return the element with the specified index minus one. *
* The returned iterator is reused by this ObjectList, so it is likely unsuitable for nested iteration. * Use {@link ObjectListIterator#ObjectListIterator(ObjectList, int)} to create a ListIterator if you need nested iteration. * * @param index * @throws IndexOutOfBoundsException {@inheritDoc} */ @Override public @NonNull ObjectListIterator listIterator (int index) { if (iterator1 == null || iterator2 == null) { iterator1 = new ObjectListIterator<>(this, index); iterator2 = new ObjectListIterator<>(this, index); } if (!iterator1.valid) { iterator1.reset(index); iterator1.valid = true; iterator2.valid = false; return iterator1; } iterator2.reset(index); iterator2.valid = true; iterator1.valid = false; return iterator2; } /** * Returns a list iterator over the elements in this list (in proper sequence). *
* The returned iterator is reused by this ObjectList, so it is likely unsuitable for nested iteration. * Use {@link ObjectListIterator#ObjectListIterator(ObjectList)} to create a ListIterator if you need nested iteration. * * @see #listIterator(int) */ @Override public @NonNull ObjectListIterator listIterator () { if (iterator1 == null || iterator2 == null) { iterator1 = new ObjectListIterator<>(this); iterator2 = new ObjectListIterator<>(this); } if (!iterator1.valid) { iterator1.reset(); iterator1.valid = true; iterator2.valid = false; return iterator1; } iterator2.reset(); iterator2.valid = true; iterator1.valid = false; return iterator2; } /** * Returns an iterator over the elements in this list in proper sequence. *
* The returned iterator is reused by this ObjectList, so it is likely unsuitable for nested iteration. * Use {@link ObjectListIterator#ObjectListIterator(ObjectList)} to create an Iterator if you need nested iteration. * * @return an iterator over the elements in this list in proper sequence */ @Override public @NonNull ObjectListIterator iterator () { if (iterator1 == null || iterator2 == null) { iterator1 = new ObjectListIterator<>(this); iterator2 = new ObjectListIterator<>(this); } if (!iterator1.valid) { iterator1.reset(); iterator1.valid = true; iterator2.valid = false; return iterator1; } iterator2.reset(); iterator2.valid = true; iterator1.valid = false; return iterator2; } /** * An {@link Iterator} and {@link ListIterator} over the elements of an ObjectList, while also an {@link Iterable}. * @param the generic type for the ObjectList this iterates over */ public static class ObjectListIterator implements Iterable, ListIterator { protected int index, latest = -1; protected ObjectList list; protected boolean valid = true; public ObjectListIterator (ObjectList list) { this.list = list; } public ObjectListIterator (ObjectList list, int index) { if (index < 0 || index >= list.size()) throw new IndexOutOfBoundsException("ObjectListIterator does not satisfy index >= 0 && index < list.size()"); this.list = list; this.index = index; } /** * Returns the next {@code int} element in the iteration. * * @return the next {@code int} element in the iteration * @throws NoSuchElementException if the iteration has no more elements */ @Override @Nullable public T next () { if (!valid) {throw new RuntimeException("#iterator() cannot be used nested.");} if (index >= list.size()) {throw new NoSuchElementException();} return list.get(latest = index++); } /** * Returns {@code true} if the iteration has more elements. * (In other words, returns {@code true} if {@link #next} would * return an element rather than throwing an exception.) * * @return {@code true} if the iteration has more elements */ @Override public boolean hasNext () { if (!valid) {throw new RuntimeException("#iterator() cannot be used nested.");} return index < list.size(); } /** * Returns {@code true} if this list iterator has more elements when * traversing the list in the reverse direction. (In other words, * returns {@code true} if {@link #previous} would return an element * rather than throwing an exception.) * * @return {@code true} if the list iterator has more elements when * traversing the list in the reverse direction */ @Override public boolean hasPrevious () { if (!valid) {throw new RuntimeException("#iterator() cannot be used nested.");} return index > 0 && list.notEmpty(); } /** * Returns the previous element in the list and moves the cursor * position backwards. This method may be called repeatedly to * iterate through the list backwards, or intermixed with calls to * {@link #next} to go back and forth. (Note that alternating calls * to {@code next} and {@code previous} will return the same * element repeatedly.) * * @return the previous element in the list * @throws NoSuchElementException if the iteration has no previous * element */ @Override @Nullable public T previous () { if (!valid) {throw new RuntimeException("#iterator() cannot be used nested.");} if (index <= 0 || list.isEmpty()) {throw new NoSuchElementException();} return list.get(latest = --index); } /** * Returns the index of the element that would be returned by a * subsequent call to {@link #next}. (Returns list size if the list * iterator is at the end of the list.) * * @return the index of the element that would be returned by a * subsequent call to {@code next}, or list size if the list * iterator is at the end of the list */ @Override public int nextIndex () { return index; } /** * Returns the index of the element that would be returned by a * subsequent call to {@link #previous}. (Returns -1 if the list * iterator is at the beginning of the list.) * * @return the index of the element that would be returned by a * subsequent call to {@code previous}, or -1 if the list * iterator is at the beginning of the list */ @Override public int previousIndex () { return index - 1; } /** * Removes from the list the last element that was returned by {@link * #next} or {@link #previous} (optional operation). This call can * only be made once per call to {@code next} or {@code previous}. * It can be made only if {@link #add} has not been * called after the last call to {@code next} or {@code previous}. * * @throws UnsupportedOperationException if the {@code remove} * operation is not supported by this list iterator * @throws IllegalStateException if neither {@code next} nor * {@code previous} have been called, or {@code remove} or * {@code add} have been called after the last call to * {@code next} or {@code previous} */ @Override public void remove () { if (!valid) {throw new RuntimeException("#iterator() cannot be used nested.");} if (latest == -1 || latest >= list.size()) {throw new NoSuchElementException();} list.removeAt(latest); index = latest; latest = -1; } /** * Replaces the last element returned by {@link #next} or * {@link #previous} with the specified element (optional operation). * This call can be made only if neither {@link #remove} nor {@link * #add} have been called after the last call to {@code next} or * {@code previous}. * * @param t the element with which to replace the last element returned by * {@code next} or {@code previous} * @throws UnsupportedOperationException if the {@code set} operation * is not supported by this list iterator * @throws ClassCastException if the class of the specified element * prevents it from being added to this list * @throws IllegalArgumentException if some aspect of the specified * element prevents it from being added to this list * @throws IllegalStateException if neither {@code next} nor * {@code previous} have been called, or {@code remove} or * {@code add} have been called after the last call to * {@code next} or {@code previous} */ @Override public void set (@Nullable T t) { if (!valid) {throw new RuntimeException("#iterator() cannot be used nested.");} if (latest == -1 || latest >= list.size()) {throw new NoSuchElementException();} list.set(latest, t); } /** * Inserts the specified element into the list (optional operation). * The element is inserted immediately before the element that * would be returned by {@link #next}, if any, and after the element * that would be returned by {@link #previous}, if any. (If the * list contains no elements, the new element becomes the sole element * on the list.) The new element is inserted before the implicit * cursor: a subsequent call to {@code next} would be unaffected, and a * subsequent call to {@code previous} would return the new element. * (This call increases by one the value that would be returned by a * call to {@code nextIndex} or {@code previousIndex}.) * * @param t the element to insert * @throws UnsupportedOperationException if the {@code add} method is * not supported by this list iterator * @throws ClassCastException if the class of the specified element * prevents it from being added to this list * @throws IllegalArgumentException if some aspect of this element * prevents it from being added to this list */ @Override public void add (@Nullable T t) { if (!valid) {throw new RuntimeException("#iterator() cannot be used nested.");} if (index > list.size()) {throw new NoSuchElementException();} list.insert(index, t); if(list.keepsOrder()) ++index; latest = -1; } public void reset () { index = 0; latest = -1; } public void reset (int index) { if (index < 0 || index >= list.size()) throw new IndexOutOfBoundsException("ObjectListIterator does not satisfy index >= 0 && index < list.size()"); this.index = index; latest = -1; } /** * Returns an iterator over elements of type {@code T}. * * @return a ListIterator; really this same ObjectListIterator. */ @Override public @NonNull ObjectListIterator iterator () { return this; } } /** * Gets the ObjectList of T items that this data structure holds, in the order it uses for iteration. * This method actually returns this ObjectList directly, since it extends ArrayList. * * @return this ObjectList */ @Override public ObjectList order () { return this; } /** * Switches the ordering of positions {@code a} and {@code b}, without changing any items beyond that. * * @param first the first position * @param second the second position */ @Override public void swap (int first, int second) { set(first, set(second, get(first))); } /** * Pseudo-randomly shuffles the order of this Ordered in-place. * You can use any {@link Random} class for {@code rng}; * * @param rng any {@link Random} class */ @Override public void shuffle (Random rng) { for (int i = size() - 1; i > 0; i--) { set(i, set(rng.nextInt(i + 1), get(i))); } } /** * Returns a {@code T} item from anywhere in this ObjectList, chosen pseudo-randomly using {@code random}. * If this ObjectList is empty, throws an {@link IllegalStateException}. * * @param random a {@link Random} or a subclass * @return a pseudo-randomly selected item from this ObjectLists */ @Override public T random (Random random) { final int n = size(); if (n == 0) {throw new IllegalStateException("ObjectList is empty.");} return get(random.nextInt(n)); } /** * Reduces the size of the array to the specified size. If the array is already smaller than the specified * size, no action is taken. */ public void truncate (int newSize) { if (size() > newSize) {removeRange(newSize, size());} } @Override public void reverse () { Collections.reverse(this); } /** * Sorts this ObjectList based on the natural order of its elements; {@code T} must implement {@link Comparable} * for this to succeed. */ public void sort () { ObjectComparators.sort(this, null); } /** * Sorts this ObjectList using the given Comparator. If the Comparator is null, then this sorts based on the * natural order of its elements, and {@code T} must implement {@link Comparable}. *
* This is implemented explicitly and not annotated with Override because of Android limitations. * * @param c a Comparator that can compare T items, or null to use the natural order of Comparable T items */ public void sort (@Nullable Comparator c) { ObjectComparators.sort(this, c); } /** * Sorts this ObjectList based on the natural order of its elements; {@code T} must implement {@link Comparable} * for this to succeed. *
* This uses the TimSort implementation in {@link java.util.Arrays}, instead of the in-place mergesort used by * {@link #sort()}. TimSort tends to be faster for many inputs, but uses more memory. Future JDK versions may * change how {@link ArrayList#sort(Comparator)} works, which would change this as well. */ public void sortJDK () { super.sort(null); } /** * Sorts this ObjectList using the given Comparator. If the Comparator is null, then this sorts based on the * natural order of its elements, and {@code T} must implement {@link Comparable}. *
* This uses the TimSort implementation in {@link java.util.Arrays}, instead of the in-place mergesort used by * {@link #sort()}. TimSort tends to be faster for many inputs, but uses more memory. Future JDK versions may * change how {@link ArrayList#sort(Comparator)} works, which would change this as well. * * @param c a Comparator that can compare T items, or null to use the natural order of Comparable T items */ public void sortJDK (@Nullable Comparator c) { super.sort(c); } /** * Constructs an empty list given the type as a generic type argument. * This is usually less useful than just using the constructor, but can be handy * in some code-generation scenarios when you don't know how many arguments you will have. * * @param the type of items; must be given explicitly * @return a new list containing nothing */ public static ObjectList with () { return new ObjectList<>(0); } /** * Creates a new ObjectList that holds only the given item, but can be resized. * @param item one T item * @return a new ObjectList that holds the given item * @param the type of item, typically inferred */ public static ObjectList with (T item) { ObjectList list = new ObjectList<>(1); list.add(item); return list; } /** * Creates a new ObjectList that holds only the given items, but can be resized. * @param item0 a T item * @param item1 a T item * @return a new ObjectList that holds the given items * @param the type of item, typically inferred */ public static ObjectList with (T item0, T item1) { ObjectList list = new ObjectList<>(2); list.add(item0, item1); return list; } /** * Creates a new ObjectList that holds only the given items, but can be resized. * @param item0 a T item * @param item1 a T item * @param item2 a T item * @return a new ObjectList that holds the given items * @param the type of item, typically inferred */ public static ObjectList with (T item0, T item1, T item2) { ObjectList list = new ObjectList<>(3); list.add(item0, item1, item2); return list; } /** * Creates a new ObjectList that holds only the given items, but can be resized. * @param item0 a T item * @param item1 a T item * @param item2 a T item * @param item3 a T item * @return a new ObjectList that holds the given items * @param the type of item, typically inferred */ public static ObjectList with (T item0, T item1, T item2, T item3) { ObjectList list = new ObjectList<>(4); list.add(item0, item1, item2, item3); return list; } /** * Creates a new ObjectList that holds only the given items, but can be resized. * @param item0 a T item * @param item1 a T item * @param item2 a T item * @param item3 a T item * @param item4 a T item * @return a new ObjectList that holds the given items * @param the type of item, typically inferred */ public static ObjectList with (T item0, T item1, T item2, T item3, T item4) { ObjectList list = new ObjectList<>(5); list.add(item0, item1, item2, item3); list.add(item4); return list; } /** * Creates a new ObjectList that holds only the given items, but can be resized. * @param item0 a T item * @param item1 a T item * @param item2 a T item * @param item3 a T item * @param item4 a T item * @param item5 a T item * @return a new ObjectList that holds the given items * @param the type of item, typically inferred */ public static ObjectList with (T item0, T item1, T item2, T item3, T item4, T item5) { ObjectList list = new ObjectList<>(6); list.add(item0, item1, item2, item3); list.add(item4, item5); return list; } /** * Creates a new ObjectList that holds only the given items, but can be resized. * @param item0 a T item * @param item1 a T item * @param item2 a T item * @param item3 a T item * @param item4 a T item * @param item5 a T item * @param item6 a T item * @return a new ObjectList that holds the given items * @param the type of item, typically inferred */ public static ObjectList with (T item0, T item1, T item2, T item3, T item4, T item5, T item6) { ObjectList list = new ObjectList<>(7); list.add(item0, item1, item2, item3); list.add(item4, item5, item6); return list; } /** * Creates a new ObjectList that holds only the given items, but can be resized. * @param item0 a T item * @param item1 a T item * @param item2 a T item * @param item3 a T item * @param item4 a T item * @param item5 a T item * @param item6 a T item * @return a new ObjectList that holds the given items * @param the type of item, typically inferred */ public static ObjectList with (T item0, T item1, T item2, T item3, T item4, T item5, T item6, T item7) { ObjectList list = new ObjectList<>(8); list.add(item0, item1, item2, item3); list.add(item4, item5, item6, item7); return list; } /** * Creates a new ObjectList that will hold the items in the given array or varargs. * This overload will only be used when an array is supplied and the type of the * items requested is the component type of the array, or if varargs are used and * there are 9 or more arguments. * @param varargs either 0 or more T items, or an array of T * @return a new ObjectList that holds the given T items * @param the type of items, typically inferred by all the items being the same type */ @SafeVarargs public static ObjectList with (T... varargs) { return new ObjectList<>(varargs); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy