Hello, everyone! My next proposal for the "Collections" utility class is a bunch of methods (similar to unmodifiable[...]) which would return not an unmodifiable List|Map|Set, but a constant-sized one. That is, all methods which get|set|... elements would work as earlier, but methods which would alter the size of the underlying collection (add|put|remove|retain|...) would throw UnsupportedOperationException.
So the new logic hoerarchy would be: 1) Unmodifiable[something] -- very strict 2) ConstantSized[something] -- less strict 3) [Usual collections] A constant-sized-list would be nearly same as an unmodifiable-list, with the exception that set(int index) would be allowed. A constant-sized-map would be nearly same as an unmodifiable-map, with the exception that put(K key, V value) on EXISTING keys would be allowed. I have no opinion of the usability of this proposal for Maps or Sets (it could make sense, but it could make none). But I am very sure, that for Lists it is very useful. What do you think of such a proposal? Not too specific? I, for myself, need such constant-sized collections often. ( I don't know about the name. ConstantSized[...]? NonResizable[...]? Sealed[...]? ) Please take a look at a proposal for a ConstantSizedList: import java.util.*; /** * Wrapps around an ArrayList and prevents all resizing methods by throwing * an UnsupportedOperationException. The underlying ArrayList still may be changed. * * The underlying ArrayList is sealed by following means: * - methods which return an iterator use Collections.unmodifiableList(...); * - adding, clearing, removing, retaining methods throw UnsupportedOperationException; * - all other methods are delegated to the underlying ArrayList. */ public final class ConstantSizeArrayList<T> implements List<T>, RandomAccess, Cloneable { private final static RuntimeException ex = new UnsupportedOperationException(ConstantSizeArrayList.class + " doesn't allow methods which resize the underlying collection"); private final ArrayList<T> underlying; public ConstantSizeArrayList(ArrayList<T> underlying) { this.underlying = underlying; underlying.trimToSize(); } @Override public String toString() { return underlying.toString(); } @Override public boolean containsAll(Collection<?> c) { return underlying.containsAll(c); } @Override public int hashCode() { return underlying.hashCode(); } @Override public boolean equals(Object o) { return underlying.equals(o); } @Override public <T> T[] toArray(T[] a) { return underlying.toArray(a); } @Override public Object[] toArray() { return underlying.toArray(); } @Override public List<T> subList(int fromIndex, int toIndex) { return underlying.subList(fromIndex, toIndex); } @Override public int size() { return underlying.size(); } @Override public T set(int index, T element) { return underlying.set(index, element); } @Override public Iterator<T> iterator() { return Collections.unmodifiableList(underlying).iterator(); } @Override public ListIterator<T> listIterator() { return Collections.unmodifiableList(underlying).listIterator(); } @Override public ListIterator<T> listIterator(int index) { return Collections.unmodifiableList(underlying).listIterator(index); } @Override public int lastIndexOf(Object o) { return underlying.lastIndexOf(o); } @Override public boolean isEmpty() { return underlying.isEmpty(); } @Override public int indexOf(Object o) { return underlying.indexOf(o); } @Override public T get(int index) { return underlying.get(index); } @Override @SuppressWarnings("element-type-mismatch") public boolean contains(Object o) { return underlying.contains(o); } // TODO delegating clone: is that OK? @Override public Object clone() { return underlying.clone(); } @Override public void clear() { throw ex; } @Override public boolean addAll(int index, Collection<? extends T> c) { throw ex; } @Override public boolean addAll(Collection<? extends T> c) { throw ex; } @Override public void add(int index, T element) { throw ex; } @Override public boolean add(T e) { throw ex; } @Override public boolean retainAll(Collection<?> c) { throw ex; } @Override public boolean removeAll(Collection<?> c) { throw ex; } @Override public boolean remove(Object o) { throw ex; } @Override public T remove(int index) { throw ex; } } Best regards, Ivan G Shevchenko