minecraft-source/src/net/minecraft/util/CrudeIncrementalIntIdentity...

148 lines
4.4 KiB
Java

package net.minecraft.util;
import java.util.Arrays;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterators;
import java.util.Iterator;
import javax.annotation.Nullable;
import net.minecraft.core.IdMap;
public class CrudeIncrementalIntIdentityHashBiMap<K> implements IdMap<K> {
private static final Object EMPTY_SLOT;
private K[] keys;
private int[] values;
private K[] byId;
private int nextId;
private int size;
public CrudeIncrementalIntIdentityHashBiMap(int integer) {
integer /= (int)0.8f;
this.keys = (K[])new Object[integer];
this.values = new int[integer];
this.byId = (K[])new Object[integer];
}
public int getId(@Nullable final K object) {
return this.getValue(this.indexOf(object, this.hash(object)));
}
@Nullable
@Override
public K byId(final int integer) {
if (integer < 0 || integer >= this.byId.length) {
return null;
}
return this.byId[integer];
}
private int getValue(final int integer) {
if (integer == -1) {
return -1;
}
return this.values[integer];
}
public int add(final K object) {
final int integer3 = this.nextId();
this.addMapping(object, integer3);
return integer3;
}
private int nextId() {
while (this.nextId < this.byId.length && this.byId[this.nextId] != null) {
++this.nextId;
}
return this.nextId;
}
private void grow(final int integer) {
final K[] arr3 = this.keys;
final int[] arr4 = this.values;
this.keys = (K[])new Object[integer];
this.values = new int[integer];
this.byId = (K[])new Object[integer];
this.nextId = 0;
this.size = 0;
for (int integer2 = 0; integer2 < arr3.length; ++integer2) {
if (arr3[integer2] != null) {
this.addMapping(arr3[integer2], arr4[integer2]);
}
}
}
public void addMapping(final K object, final int integer) {
final int integer2 = Math.max(integer, this.size + 1);
if (integer2 >= this.keys.length * 0.8f) {
int integer3;
for (integer3 = this.keys.length << 1; integer3 < integer; integer3 <<= 1) {}
this.grow(integer3);
}
int integer3 = this.findEmpty(this.hash(object));
this.keys[integer3] = object;
this.values[integer3] = integer;
this.byId[integer] = object;
++this.size;
if (integer == this.nextId) {
++this.nextId;
}
}
private int hash(@Nullable final K object) {
return (Mth.murmurHash3Mixer(System.identityHashCode(object)) & Integer.MAX_VALUE) % this.keys.length;
}
private int indexOf(@Nullable final K object, final int integer) {
for (int integer2 = integer; integer2 < this.keys.length; ++integer2) {
if (this.keys[integer2] == object) {
return integer2;
}
if (this.keys[integer2] == CrudeIncrementalIntIdentityHashBiMap.EMPTY_SLOT) {
return -1;
}
}
for (int integer2 = 0; integer2 < integer; ++integer2) {
if (this.keys[integer2] == object) {
return integer2;
}
if (this.keys[integer2] == CrudeIncrementalIntIdentityHashBiMap.EMPTY_SLOT) {
return -1;
}
}
return -1;
}
private int findEmpty(final int integer) {
for (int integer2 = integer; integer2 < this.keys.length; ++integer2) {
if (this.keys[integer2] == CrudeIncrementalIntIdentityHashBiMap.EMPTY_SLOT) {
return integer2;
}
}
for (int integer2 = 0; integer2 < integer; ++integer2) {
if (this.keys[integer2] == CrudeIncrementalIntIdentityHashBiMap.EMPTY_SLOT) {
return integer2;
}
}
throw new RuntimeException("Overflowed :(");
}
@Override
public Iterator<K> iterator() {
return Iterators.<K>filter(Iterators.<K>forArray(this.byId), Predicates.notNull());
}
public void clear() {
Arrays.fill(this.keys, null);
Arrays.fill(this.byId, null);
this.nextId = 0;
this.size = 0;
}
public int size() {
return this.size;
}
static {
EMPTY_SLOT = null;
}
}