From 5634d9f701acea733fbe8c0f47c60369acfd56cd Mon Sep 17 00:00:00 2001 From: Wesley Wolfe Date: Tue, 2 Apr 2013 07:52:17 -0500 Subject: [PATCH] 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. --- .../craftbukkit/util/WeakCollection.java | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/main/java/org/bukkit/craftbukkit/util/WeakCollection.java 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 0000000000..d63348aff1 --- /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 implements Collection { + static final Object NO_VALUE = new Object(); + private final Collection> collection; + + public WeakCollection() { + collection = new ArrayList>(); + } + + public boolean add(T value) { + Validate.notNull(value, "Cannot add null value"); + return collection.add(new WeakReference(value)); + } + + public boolean addAll(Collection collection) { + Collection> values = this.collection; + boolean ret = false; + for (T value : collection) { + Validate.notNull(value, "Cannot add null value"); + ret |= values.add(new WeakReference(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 iterator() { + return new Iterator() { + Iterator> it = collection.iterator(); + Object value = NO_VALUE; + + @Override + public boolean hasNext() { + Object value = this.value; + if (value != null && value != NO_VALUE) { + return true; + } + + Iterator> it = this.it; + value = null; + + while (it.hasNext()) { + WeakReference 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 it = this.iterator(); + while (it.hasNext()) { + if (object.equals(it.next())) { + it.remove(); + return true; + } + } + return false; + } + + public boolean removeAll(Collection collection) { + Iterator 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 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[] toArray(T[] array) { + return toCollection().toArray(array); + } + + private Collection toCollection() { + ArrayList collection = new ArrayList(); + for (T value : this) { + collection.add(value); + } + return collection; + } +}