212 lines
5 KiB
Java
212 lines
5 KiB
Java
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<T> extends AbstractSet<T> {
|
|
private static final int DEFAULT_INITIAL_CAPACITY = 10;
|
|
private final Comparator<T> comparator;
|
|
T[] contents;
|
|
int size;
|
|
|
|
private SortedArraySet(int initialCapacity, Comparator<T> 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 <T extends Comparable<T>> SortedArraySet<T> create() {
|
|
return create(10);
|
|
}
|
|
|
|
public static <T extends Comparable<T>> SortedArraySet<T> create(int initialCapacity) {
|
|
return new SortedArraySet<>(initialCapacity, Comparator.naturalOrder());
|
|
}
|
|
|
|
public static <T> SortedArraySet<T> create(Comparator<T> comparator) {
|
|
return create(comparator, 10);
|
|
}
|
|
|
|
public static <T> SortedArraySet<T> create(Comparator<T> comparator, int initialCapacity) {
|
|
return new SortedArraySet<>(initialCapacity, comparator);
|
|
}
|
|
|
|
private static <T> 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<T> 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> 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<T> {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|