Added WeakList
This commit is contained in:
parent
797b1a74fc
commit
658a1f994e
4 changed files with 246 additions and 2 deletions
|
@ -6,6 +6,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
|
||||||
import gnu.trove.map.TIntObjectMap;
|
import gnu.trove.map.TIntObjectMap;
|
||||||
import gnu.trove.map.hash.TIntObjectHashMap;
|
import gnu.trove.map.hash.TIntObjectHashMap;
|
||||||
|
@ -14,7 +15,7 @@ import gnu.trove.map.hash.TIntObjectHashMap;
|
||||||
* @author TheDarkDnKTv
|
* @author TheDarkDnKTv
|
||||||
* An multi inventory adapter used for multiblocks
|
* An multi inventory adapter used for multiblocks
|
||||||
*/
|
*/
|
||||||
public class InventoryHandlerList<E> extends AbstractList<E> {
|
public class InventoryHandlerList<E> extends AbstractList<E> implements RandomAccess {
|
||||||
|
|
||||||
protected final TIntObjectMap<List<E>> indexMapping;
|
protected final TIntObjectMap<List<E>> indexMapping;
|
||||||
protected final Map<Integer, Integer> offsetMap;
|
protected final Map<Integer, Integer> offsetMap;
|
||||||
|
|
|
@ -3,6 +3,7 @@ package gregtechmod.api.util;
|
||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array to list adapter with range controll function
|
* An array to list adapter with range controll function
|
||||||
|
@ -10,7 +11,7 @@ import java.util.Objects;
|
||||||
*
|
*
|
||||||
* @author TheDarkDnKTv
|
* @author TheDarkDnKTv
|
||||||
*/
|
*/
|
||||||
public class ListAdapter<E> extends AbstractList<E> {
|
public class ListAdapter<E> extends AbstractList<E> implements RandomAccess {
|
||||||
protected E[] data;
|
protected E[] data;
|
||||||
private int idxStart;
|
private int idxStart;
|
||||||
private int idxEnd;
|
private int idxEnd;
|
||||||
|
|
162
src/main/java/gregtechmod/api/util/WeakList.java
Normal file
162
src/main/java/gregtechmod/api/util/WeakList.java
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
package gregtechmod.api.util;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.AbstractList;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.RandomAccess;
|
||||||
|
|
||||||
|
|
||||||
|
/** Simple wrapper of Weak References & ArrayList
|
||||||
|
*
|
||||||
|
* @author TheDarkDnKTv
|
||||||
|
*
|
||||||
|
* @see {@link WeakReference}
|
||||||
|
* @see {@link ArrayList}
|
||||||
|
*/
|
||||||
|
public class WeakList<E> extends AbstractList<E> implements RandomAccess, Cloneable {
|
||||||
|
|
||||||
|
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||||
|
private static final int DEFAULT_CAPACITY = 10;
|
||||||
|
|
||||||
|
private transient WeakReference<E>[] elementData;
|
||||||
|
private int size = 0;
|
||||||
|
|
||||||
|
public WeakList() {
|
||||||
|
elementData = newArray(DEFAULT_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeakList(int initialCapacity) {
|
||||||
|
if (initialCapacity < 0 || initialCapacity > MAX_ARRAY_SIZE)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
elementData = newArray(DEFAULT_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeakList(Collection<? extends E> c) {
|
||||||
|
elementData = newArray(c.size() + 1);
|
||||||
|
int idx = 0;
|
||||||
|
Iterator<? extends E> iter = c.iterator();
|
||||||
|
while (iter.hasNext())
|
||||||
|
elementData[idx++] = new WeakReference<E>(iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E get(int idx) {
|
||||||
|
rangeCheck(idx);
|
||||||
|
WeakReference<E> ref = elementData[idx];
|
||||||
|
return ref == null ? null : ref.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(int index, E element) {
|
||||||
|
if (index < 0)
|
||||||
|
throw new IllegalArgumentException("Index: " + index);
|
||||||
|
ensureCapacityInternal(size + 1);
|
||||||
|
System.arraycopy(elementData, index, elementData, index + 1, size - index);
|
||||||
|
elementData[index] = new WeakReference<>(element);
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E remove(int index) {
|
||||||
|
rangeCheck(index);
|
||||||
|
|
||||||
|
modCount++;
|
||||||
|
E oldValue = elementData[index] == null ? null : elementData[index].get();
|
||||||
|
|
||||||
|
int numMoved = size - index - 1;
|
||||||
|
if (numMoved > 0)
|
||||||
|
System.arraycopy(elementData, index+1, elementData, index, numMoved);
|
||||||
|
elementData[--size] = null;
|
||||||
|
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
modCount++;
|
||||||
|
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
elementData[i] = null;
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link WeakList#get()} but giving an otional
|
||||||
|
*/
|
||||||
|
public Optional<E> getSecure(int idx) {
|
||||||
|
return Optional.ofNullable(this.get(idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect of {@link WeakReference#isEnqueued()}
|
||||||
|
*/
|
||||||
|
public boolean isEnqueued(int idx) {
|
||||||
|
rangeCheck(idx);
|
||||||
|
WeakReference<E> ref = elementData[idx];
|
||||||
|
return ref == null ? false : ref.isEnqueued();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect of {@link WeakReference#clear()}
|
||||||
|
*/
|
||||||
|
public void clear(int idx) {
|
||||||
|
rangeCheck(idx);
|
||||||
|
WeakReference<E> ref = elementData[idx];
|
||||||
|
if (ref != null) ref.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect of {@link WeakReference#enqueue()}
|
||||||
|
*/
|
||||||
|
public boolean enqueue(int idx) {
|
||||||
|
rangeCheck(idx);
|
||||||
|
WeakReference<E> ref = elementData[idx];
|
||||||
|
return ref == null ? false : ref.enqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rangeCheck(int idx) {
|
||||||
|
if (idx < 0 || idx >= elementData.length) {
|
||||||
|
throw new ArrayIndexOutOfBoundsException("Index: " + idx + ", Size: " + size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private WeakReference<E>[] newArray(int size) {
|
||||||
|
return (WeakReference<E>[]) new WeakReference[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureCapacityInternal(int minCapacity) {
|
||||||
|
modCount++;
|
||||||
|
|
||||||
|
if (minCapacity - elementData.length > 0)
|
||||||
|
grow(minCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void grow(int minCapacity) {
|
||||||
|
int oldCapacity = elementData.length;
|
||||||
|
int newCapacity = oldCapacity + (oldCapacity >> 1);
|
||||||
|
if (newCapacity - minCapacity < 0)
|
||||||
|
newCapacity = minCapacity;
|
||||||
|
if (newCapacity - MAX_ARRAY_SIZE > 0)
|
||||||
|
newCapacity = hugeCapacity(minCapacity);
|
||||||
|
elementData = Arrays.copyOf(elementData, newCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int hugeCapacity(int minCapacity) {
|
||||||
|
if (minCapacity < 0)
|
||||||
|
throw new OutOfMemoryError();
|
||||||
|
return (minCapacity > MAX_ARRAY_SIZE) ?
|
||||||
|
Integer.MAX_VALUE :
|
||||||
|
MAX_ARRAY_SIZE;
|
||||||
|
}
|
||||||
|
}
|
80
src/test/java/gregtechmod/tests/WeakListTest.java
Normal file
80
src/test/java/gregtechmod/tests/WeakListTest.java
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package gregtechmod.tests;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.TestInstance;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
|
||||||
|
import gregtechmod.api.util.WeakList;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author TheDarkDnKTv
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@TestInstance(Lifecycle.PER_CLASS)
|
||||||
|
@TestMethodOrder(OrderAnnotation.class)
|
||||||
|
public class WeakListTest {
|
||||||
|
|
||||||
|
WeakList<Obj> testList;
|
||||||
|
|
||||||
|
public WeakListTest() {
|
||||||
|
testList = new WeakList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
public void size() {
|
||||||
|
assertTrue(testList.toString(), testList.size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
public void add() {
|
||||||
|
testList.add(new Obj("LMAO"));
|
||||||
|
testList.add(new Obj("KEK"));
|
||||||
|
testList.add(new Obj("KEK1"));
|
||||||
|
testList.add(new Obj("KEK2"));
|
||||||
|
testList.add(new Obj("KEK3"));
|
||||||
|
System.out.println(testList);
|
||||||
|
assertTrue(testList.toString(), testList.size() == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(3)
|
||||||
|
public void get() {
|
||||||
|
Obj a = testList.get(1);
|
||||||
|
assertTrue("KEK".equals(a.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4)
|
||||||
|
public void remove() {
|
||||||
|
Obj a = testList.remove(3);
|
||||||
|
System.out.println(a);
|
||||||
|
assertTrue(testList.size() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(5)
|
||||||
|
public void gc() {
|
||||||
|
System.gc();
|
||||||
|
System.err.println(testList);
|
||||||
|
assertTrue(!testList.getSecure(0).isPresent());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Obj {
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
Obj(String value) {this.value = value;}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue