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

com.github.tommyettinger.gand.ds.IntCollection Maven / Gradle / Ivy

/*
 * Copyright (c) 2022-2023 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.gand.ds;

import com.github.tommyettinger.gand.utils.IntConsumer;
import com.github.tommyettinger.gand.utils.IntIterator;
import com.github.tommyettinger.gand.utils.IntPredicate;

import java.util.Iterator;

/**
 * Analogous to {@link java.util.Collection} but for primitive ints, this is built around
 * the primitive-specialized iterator {@link IntIterator} instead of the generic {@link Iterator}.
 * This is not necessarily a modifiable collection.
 */
public interface IntCollection {
	int size ();

	default boolean isEmpty () {
		return size() == 0;
	}

	default boolean notEmpty () {
		return size() != 0;
	}

	boolean add(int item);

	boolean remove(int item);

	boolean contains(int item);

	default boolean addAll(IntCollection other) {
		IntIterator it = other.iterator();
		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(IntCollection other) {
		IntIterator it = other.iterator(), 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(IntCollection other) {
		IntIterator it = other.iterator();
		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(IntCollection other) {
		IntIterator it = other.iterator();
		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(IntCollection other) {
		IntIterator it = other.iterator();
		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(IntCollection other) {
		boolean changed = false;
		IntIterator it = iterator();
		while (it.hasNext()) {
			if (!other.contains(it.nextInt())) {
				it.remove();
				changed = true;
			}
		}
		return changed;
	}

	IntIterator iterator();

	void clear ();

	@Override
	int hashCode ();

	@Override
	boolean equals (Object other);

	/**
	 * 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 IntCollection}
	 * 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 IntCollection with another IntCollection by checking their identity, * their types (both must implement IntCollection), and their sizes, before checking if other * contains each item in this IntCollection, 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 * IntCollection, but that isn't necessary for {@code other}. * @param other another Object that should be a IntCollection * @return true if other is another IntCollection with exactly the same items, false otherwise */ default boolean areEqual(Object other) { if(this == other) return true; if(!(other instanceof IntCollection)) return false; IntCollection pc = (IntCollection) other; if(size() != pc.size()) return false; IntIterator it = iterator(); while (it.hasNext()) { if(pc.contains(it.nextInt())) return false; } return true; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy