package org.rr.commons.collection;
import java.lang.ref.WeakReference;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
/**
* This list stores objects automatically using weak references. Objects are added and removed from the list as normal, but may turn to null at any point (ie,
* indexOf(x) followed by get(x) may return null). The weak references are only removed when the trimToSize method is called so that the indices remain constant
* otherwise.
* <p>
*
* @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
* @version $Revision: 1.3 $
*/
public class WeakList<T> extends AbstractList<T> {
/* list of weak references */
private ArrayList<WeakReference<T>> refs = new ArrayList<WeakReference<T>>();
/**
* Create a weak random-access list.
*/
public WeakList() {
}
/**
* Extract the hard reference out of a weak reference.
*/
private T deref(WeakReference<T> o) {
if (o != null) {
return o.get();
} else {
return null;
}
}
/**
* Returns the object at the specified index, or null if the object has been collected.
*/
public T get(int index) {
return deref(refs.get(index));
}
/**
* Returns the size of the list, including already collected objects.
*/
public int size() {
return refs.size();
}
/**
* Sets the object at the specified position and returns the previous object at that position or null if it was already collected.
*/
public T set(int index, T element) {
return deref(refs.set(index, new WeakReference<T>(element)));
}
/**
* Inserts the object at the specified position in the list. Automatically creates a weak reference to the object.
*/
public void add(int index, T element) {
refs.add(index, new WeakReference<T>(element));
}
/**
* Removes the object at the specified position and returns it or returns null if it was already collected.
*/
public T remove(int index) {
return deref(refs.remove(index));
}
/**
* Returns a list of hard references to the objects. The returned list does not include the collected elements, so its indices do not necessarily correlate
* with those of this list.
*/
public List<T> hardList() {
List<T> result = new ArrayList<>();
for (int i = 0; i < size(); i++) {
T tmp = get(i);
if (tmp != null)
result.add(tmp);
}
return result;
}
/**
* Compacts the list by removing references to collected objects.
*/
public void trimToSize() {
for (int i = size(); i-- > 0;)
if (get(i) == null)
remove(i);
}
}