package com.bergerkiller.bukkit.common.collections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
/**
* A List implementation that only stores unique values, like a Set does
*
* @param <E> - Element type
*/
public class UniqueList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
private final HashSet<E> uniqueElements;
/**
* Constructs a new UniqueList with a capacity of 10
*/
public UniqueList() {
this(10);
}
/**
* Constructs a new UniqueList containing all the unique contents added in order
*
* @param contents to add to the newly constructed UniqueList
*/
public UniqueList(Collection<E> contents) {
this(contents.size());
addAll(contents);
}
/**
* Constructs a new UniqueList with the initial capacity
*
* @param capacity to use
*/
public UniqueList(int capacity) {
super(capacity);
uniqueElements = new HashSet<E>(capacity);
}
@Override
public void clear() {
super.clear();
uniqueElements.clear();
}
@Override
public boolean contains(Object o) {
return uniqueElements.contains(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return uniqueElements.containsAll(c);
}
@Override
public boolean remove(Object o) {
return uniqueElements.remove(o) && super.remove(o);
}
@Override
public boolean add(E e) {
return uniqueElements.add(e) && super.add(e);
}
@Override
public E remove(int index) {
final E removed = super.remove(index);
uniqueElements.remove(removed);
return removed;
}
@Override
public E set(int index, E e) {
E oldValue = get(index);
if (oldValue != e) {
uniqueElements.remove(oldValue);
if (uniqueElements.add(e)) {
// Added
super.set(index, e);
} else {
// Restore - we can't add this!
uniqueElements.add(oldValue);
}
}
return oldValue;
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return CollectionBasics.addAll(this, elements);
}
@Override
public boolean removeAll(Collection<?> elements) {
if (this.size() <= 10) {
return CollectionBasics.removeAll(this, elements);
} else {
// Faster algortihm for larger amounts of elements
final boolean changed = uniqueElements.removeAll(elements);
if (changed) {
Iterator<E> iter = this.iterator();
while (iter.hasNext()) {
if (!uniqueElements.contains(iter.next())) {
iter.remove();
}
}
}
return changed;
}
}
@Override
public boolean retainAll(Collection<?> elements) {
return CollectionBasics.retainAll(this, elements);
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
for (int i = fromIndex; i < toIndex; i++) {
uniqueElements.remove(get(i));
}
super.removeRange(fromIndex, toIndex);
}
}