summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWesley Wolfe <weswolf@aol.com>2013-04-02 07:52:17 -0500
committerWesley Wolfe <weswolf@aol.com>2013-04-04 01:05:47 -0500
commit5634d9f701acea733fbe8c0f47c60369acfd56cd (patch)
tree6ebe10dba4b6ebd12ffa5583a82be4e5dfd12ba5 /src
parent3f637d17248df4fdec084d238b7eb4a1f6f15c1c (diff)
downloadcraftbukkit-5634d9f701acea733fbe8c0f47c60369acfd56cd.tar
craftbukkit-5634d9f701acea733fbe8c0f47c60369acfd56cd.tar.gz
craftbukkit-5634d9f701acea733fbe8c0f47c60369acfd56cd.tar.lz
craftbukkit-5634d9f701acea733fbe8c0f47c60369acfd56cd.tar.xz
craftbukkit-5634d9f701acea733fbe8c0f47c60369acfd56cd.zip
Add a WeakCollection utility class.
This class is designed to be an invisible layer between a normal collection, and one that silently loses entries because they are only weakly referencable. Some operations have additional overhead to be semantically correct, but it maintains the equals contract for all entries, as opposed to identity. It does not support the equals or hash code method as it cannot easily have the transitive and commutative properties.
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java b/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java
new file mode 100644
index 00000000..d63348af
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java
@@ -0,0 +1,173 @@
+package org.bukkit.craftbukkit.util;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.lang.Validate;
+
+
+public final class WeakCollection<T> implements Collection<T> {
+ static final Object NO_VALUE = new Object();
+ private final Collection<WeakReference<T>> collection;
+
+ public WeakCollection() {
+ collection = new ArrayList<WeakReference<T>>();
+ }
+
+ public boolean add(T value) {
+ Validate.notNull(value, "Cannot add null value");
+ return collection.add(new WeakReference<T>(value));
+ }
+
+ public boolean addAll(Collection<? extends T> collection) {
+ Collection<WeakReference<T>> values = this.collection;
+ boolean ret = false;
+ for (T value : collection) {
+ Validate.notNull(value, "Cannot add null value");
+ ret |= values.add(new WeakReference<T>(value));
+ }
+ return ret;
+ }
+
+ public void clear() {
+ collection.clear();
+ }
+
+ public boolean contains(Object object) {
+ if (object == null) {
+ return false;
+ }
+ for (T compare : this) {
+ if (object.equals(compare)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean containsAll(Collection<?> collection) {
+ return toCollection().containsAll(collection);
+ }
+
+ public boolean isEmpty() {
+ return !iterator().hasNext();
+ }
+
+ public Iterator<T> iterator() {
+ return new Iterator<T>() {
+ Iterator<WeakReference<T>> it = collection.iterator();
+ Object value = NO_VALUE;
+
+ @Override
+ public boolean hasNext() {
+ Object value = this.value;
+ if (value != null && value != NO_VALUE) {
+ return true;
+ }
+
+ Iterator<WeakReference<T>> it = this.it;
+ value = null;
+
+ while (it.hasNext()) {
+ WeakReference<T> ref = it.next();
+ value = ref.get();
+ if (value == null) {
+ it.remove();
+ } else {
+ this.value = value;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public T next() throws NoSuchElementException {
+ if (!hasNext()) {
+ throw new NoSuchElementException("No more elements");
+ }
+
+ @SuppressWarnings("unchecked")
+ T value = (T) this.value;
+ this.value = NO_VALUE;
+ return value;
+ }
+
+ @Override
+ public void remove() throws IllegalStateException {
+ if (value != NO_VALUE) {
+ throw new IllegalStateException("No last element");
+ }
+
+ value = null;
+ it.remove();
+ }
+ };
+ }
+
+ public boolean remove(Object object) {
+ if (object == null) {
+ return false;
+ }
+
+ Iterator<T> it = this.iterator();
+ while (it.hasNext()) {
+ if (object.equals(it.next())) {
+ it.remove();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean removeAll(Collection<?> collection) {
+ Iterator<T> it = this.iterator();
+ boolean ret = false;
+ while (it.hasNext()) {
+ if (collection.contains(it.next())) {
+ ret = true;
+ it.remove();
+ }
+ }
+ return ret;
+ }
+
+ public boolean retainAll(Collection<?> collection) {
+ Iterator<T> it = this.iterator();
+ boolean ret = false;
+ while (it.hasNext()) {
+ if (!collection.contains(it.next())) {
+ ret = true;
+ it.remove();
+ }
+ }
+ return ret;
+ }
+
+ public int size() {
+ int s = 0;
+ for (T value : this) {
+ s++;
+ }
+ return s;
+ }
+
+ public Object[] toArray() {
+ return this.toArray(new Object[0]);
+ }
+
+ public <T> T[] toArray(T[] array) {
+ return toCollection().toArray(array);
+ }
+
+ private Collection<T> toCollection() {
+ ArrayList<T> collection = new ArrayList<T>();
+ for (T value : this) {
+ collection.add(value);
+ }
+ return collection;
+ }
+}