package net.minecraft.util; import it.unimi.dsi.fastutil.objects.ObjectArrays; import java.util.AbstractSet; import java.util.Arrays; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import net.minecraft.Util; import org.jetbrains.annotations.Nullable; public class SortedArraySet extends AbstractSet { private static final int DEFAULT_INITIAL_CAPACITY = 10; private final Comparator comparator; T[] contents; int size; private SortedArraySet(int initialCapacity, Comparator comparator) { this.comparator = comparator; if (initialCapacity < 0) { throw new IllegalArgumentException("Initial capacity (" + initialCapacity + ") is negative"); } else { this.contents = (T[])castRawArray(new Object[initialCapacity]); } } public static > SortedArraySet create() { return create(10); } public static > SortedArraySet create(int initialCapacity) { return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder()); } public static SortedArraySet create(Comparator comparator) { return create(comparator, 10); } public static SortedArraySet create(Comparator comparator, int initialCapacity) { return new SortedArraySet<>(initialCapacity, comparator); } private static T[] castRawArray(Object[] array) { return (T[])array; } private int findIndex(T object) { return Arrays.binarySearch(this.contents, 0, this.size, object, this.comparator); } private static int getInsertionPosition(int index) { return -index - 1; } public boolean add(T object) { int i = this.findIndex(object); if (i >= 0) { return false; } else { int j = getInsertionPosition(i); this.addInternal(object, j); return true; } } private void grow(int size) { if (size > this.contents.length) { if (this.contents != ObjectArrays.DEFAULT_EMPTY_ARRAY) { size = Util.growByHalf(this.contents.length, size); } else if (size < 10) { size = 10; } Object[] objects = new Object[size]; System.arraycopy(this.contents, 0, objects, 0, this.size); this.contents = (T[])castRawArray(objects); } } private void addInternal(T element, int index) { this.grow(this.size + 1); if (index != this.size) { System.arraycopy(this.contents, index, this.contents, index + 1, this.size - index); } this.contents[index] = element; this.size++; } void removeInternal(int index) { this.size--; if (index != this.size) { System.arraycopy(this.contents, index + 1, this.contents, index, this.size - index); } this.contents[this.size] = null; } private T getInternal(int index) { return this.contents[index]; } public T addOrGet(T element) { int i = this.findIndex(element); if (i >= 0) { return this.getInternal(i); } else { this.addInternal(element, getInsertionPosition(i)); return element; } } public boolean remove(Object object) { int i = this.findIndex((T)object); if (i >= 0) { this.removeInternal(i); return true; } else { return false; } } @Nullable public T get(T element) { int i = this.findIndex(element); return i >= 0 ? this.getInternal(i) : null; } /** * Gets the smallest element in the set */ public T first() { return this.getInternal(0); } public T last() { return this.getInternal(this.size - 1); } public boolean contains(Object object) { int i = this.findIndex((T)object); return i >= 0; } public Iterator iterator() { return new SortedArraySet.ArrayIterator(); } public int size() { return this.size; } public Object[] toArray() { return Arrays.copyOf(this.contents, this.size, Object[].class); } public U[] toArray(U[] objects) { if (objects.length < this.size) { return (U[])Arrays.copyOf(this.contents, this.size, objects.getClass()); } else { System.arraycopy(this.contents, 0, objects, 0, this.size); if (objects.length > this.size) { objects[this.size] = null; } return objects; } } public void clear() { Arrays.fill(this.contents, 0, this.size, null); this.size = 0; } public boolean equals(Object object) { if (this == object) { return true; } else { return object instanceof SortedArraySet sortedArraySet && this.comparator.equals(sortedArraySet.comparator) ? this.size == sortedArraySet.size && Arrays.equals(this.contents, sortedArraySet.contents) : super.equals(object); } } class ArrayIterator implements Iterator { private int index; private int last = -1; public boolean hasNext() { return this.index < SortedArraySet.this.size; } public T next() { if (this.index >= SortedArraySet.this.size) { throw new NoSuchElementException(); } else { this.last = this.index++; return SortedArraySet.this.contents[this.last]; } } public void remove() { if (this.last == -1) { throw new IllegalStateException(); } else { SortedArraySet.this.removeInternal(this.last); this.index--; this.last = -1; } } } }