Code: Select all
public interface EfficientCollection<T> {
int getSize();
T getItem(int index);
EfficientCollection<T> addItem(T item);
}
public class EmptyEfficientCollection<T> implements EfficientCollection<T> {
@Override
public int getSize() {
return 0;
}
@Override
public T getItem(int index) {
return null; // or throw an exception, etc
}
@Override
public EfficientCollection<T> addItem(T item) {
return new SingletonEfficientCollection<T>(item);
}
}
public class SingletonEfficientCollection<T> implements EfficientCollection<T> {
private final T item;
public SingletonEfficientCollection(T item) {
this.item = item;
}
@Override
public int getSize() {
return 1;
}
@Override
public T getItem(int index) {
return index == 0 ? item : null;
}
@Override
public EfficientCollection<T> addItem(T item) {
return new ArrayEfficientCollection<T>((T[]) new Object[] {this.item, item});
}
}
public class ArrayEfficientCollection<T> implements EfficientCollection<T> {
private final T[] items;
public SingletonEfficientCollection(T[] items) {
this.items = items;
}
@Override
public int getSize() {
return items.length;
}
@Override
public T getItem(int index) {
return items[index];
}
@Override
public EfficientCollection<T> addItem(T item) {
// figure out how best to extend the collection storage
}
}
public class WrappedEfficientCollection<T> implements EfficientCollection<T> {
private EfficientCollection<T> innerCollection = new EmptyEfficientCollection<T>();
@Override
public int getSize() {
return innerCollection.getSize();
}
@Override
public T getItem(int index) {
return innerCollection.getItem(index);
}
@Override
public EfficientCollection<T> addItem(T item) {
innerCollection = innerCollection.addItem(item); // replaces the inner collection with the chosen implementation
return this; // the user of the wrapper only ever sees the wrapper
}
}