Class ControlledArrayList<E>
- Type Parameters:
E- The element type.
- All Implemented Interfaces:
Serializable,Cloneable,Iterable<E>,Collection<E>,List<E>,RandomAccess
- Direct Known Subclasses:
HeaderList,PartList
ArrayList that allows you to control whether it's read-only via a constructor parameter.
This class provides a unique capability: it can appear as an unmodifiable list to external code (via the standard
List interface methods) while still allowing internal code to modify it through special "override" methods.
This is useful when you need to pass a list to code that should not modify it, but you still need to modify it
internally.
Features:
- Controlled Mutability: Can be configured as modifiable or unmodifiable at construction time
- Override Methods: Special methods (e.g.,
overrideAdd(Object)) bypass the unmodifiable restriction - Standard List Interface: Implements all standard
Listmethods with proper unmodifiable enforcement - Iterator Protection: Iterators returned from unmodifiable lists prevent modification operations
- Dynamic Control: Can be made unmodifiable after construction via
setUnmodifiable()
Use Cases:
- Passing a list to external code that should not modify it, while maintaining internal modification capability
- Building a list internally and then "freezing" it before exposing it to clients
- Creating a list that appears read-only to consumers but can be modified by trusted internal code
- Implementing defensive copying patterns where the original list needs to remain mutable internally
Usage:
Override Methods:
The "override" methods (e.g., overrideAdd(Object), overrideRemove(int)) bypass the unmodifiable
restriction and allow modification regardless of the list's modifiable state. These methods are intended for use
by trusted internal code that needs to modify the list even when it's marked as unmodifiable.
Iterator Behavior:
When the list is unmodifiable, iterators returned by iterator() and listIterator() are read-only.
Attempting to call Iterator.remove() or ListIterator.set(Object) on these iterators will throw
UnsupportedOperationException. However, the override methods can still be used to modify the list.
Thread Safety:
This class is not thread-safe. If multiple threads access a ControlledArrayList concurrently, and at least
one thread modifies the list structurally, it must be synchronized externally. The unmodifiable flag does not
provide thread-safety; it only controls whether standard List interface methods can modify the list.
Example - Building and Freezing:
See Also:
- See Also:
-
Field Summary
Fields inherited from class java.util.AbstractList
modCount -
Constructor Summary
ConstructorsConstructorDescriptionControlledArrayList(boolean unmodifiable) Constructor.ControlledArrayList(boolean unmodifiable, List<? extends E> list) Constructor. -
Method Summary
Modifier and TypeMethodDescriptionvoidbooleanbooleanaddAll(int index, Collection<? extends E> c) booleanaddAll(Collection<? extends E> c) protected final voidThrows anUnsupportedOperationExceptionif the unmodifiable flag is set on this list.voidclear()booleanReturnstrue if this list is modifiable through standardListinterface methods.iterator()listIterator(int index) voidoverrideAdd(int index, E element) Same asadd(int, Object)but bypasses the modifiable flag.booleanoverrideAdd(E element) Same asadd(Object)but bypasses the modifiable flag.booleanoverrideAddAll(int index, Collection<? extends E> c) Same asaddAll(int,Collection)but bypasses the modifiable flag.booleanoverrideAddAll(Collection<? extends E> c) Same asaddAll(Collection)but bypasses the modifiable flag.voidSame asclear()but bypasses the modifiable flag.Same asiterator()but bypasses the modifiable flag.overrideListIterator(int index) Same aslistIterator()but bypasses the modifiable flag.overrideRemove(int index) Same asremove(int)but bypasses the modifiable flag.booleanSame asremove(Object)but bypasses the modifiable flag.booleanoverrideRemoveAll(Collection<?> c) Same asremoveAll(Collection)but bypasses the modifiable flag.booleanoverrideRemoveIf(Predicate<? super E> filter) Same asremoveIf(Predicate)but bypasses the modifiable flag.voidoverrideReplaceAll(UnaryOperator<E> operator) Same asreplaceAll(UnaryOperator)but bypasses the modifiable flag.booleanoverrideRetainAll(Collection<?> c) Same asretainAll(Collection)but bypasses the modifiable flag.overrideSet(int index, E element) Same asset(int, Object)but bypasses the modifiable flag.voidoverrideSort(Comparator<? super E> c) Same asoverrideSort(Comparator)but bypasses the modifiable flag.remove(int index) booleanbooleanremoveAll(Collection<?> coll) booleanvoidreplaceAll(UnaryOperator<E> operator) booleanretainAll(Collection<?> c) Makes this list unmodifiable through standardListinterface methods.voidsort(Comparator<? super E> c) subList(int fromIndex, int toIndex) Methods inherited from class java.util.ArrayList
clone, contains, ensureCapacity, equals, forEach, get, hashCode, indexOf, isEmpty, lastIndexOf, removeRange, size, spliterator, toArray, toArray, trimToSizeMethods inherited from class java.util.AbstractCollection
containsAll, toStringMethods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, waitMethods inherited from interface java.util.Collection
parallelStream, stream, toArrayMethods inherited from interface java.util.List
containsAll
-
Constructor Details
-
ControlledArrayList
Constructor.Creates an empty list with the specified modifiability setting.
Example:
// Create an empty unmodifiable list ControlledArrayList<String>list =new ControlledArrayList<>(true );// Create an empty modifiable list ControlledArrayList<String>list2 =new ControlledArrayList<>(false );- Parameters:
unmodifiable- Iftrue , this list cannot be modified through normal list operation methods on theListinterface. Use override methods to modify when unmodifiable.
-
ControlledArrayList
Constructor.Creates a list with the specified initial contents and modifiability setting.
Example:
// Create an unmodifiable list with initial contents List<String>initial = List.of("a" ,"b" ,"c" ); ControlledArrayList<String>list =new ControlledArrayList<>(true ,initial );// Standard methods throw exceptions list .add("d" );// UnsupportedOperationException - Parameters:
unmodifiable- Iftrue , this list cannot be modified through normal list operation methods on theListinterface. Use override methods to modify when unmodifiable.list- The initial contents of this list. Must not benull .
-
-
Method Details
-
add
-
add
-
addAll
-
addAll
-
clear
-
isModifiable
Returnstrue if this list is modifiable through standardListinterface methods.Note that even when this method returns
false , the list can still be modified using the override methods (e.g.,overrideAdd(Object)).Example:
ControlledArrayList<String>
list =new ControlledArrayList<>(true );assertFalse (list .isModifiable());// Standard methods cannot modify ControlledArrayList<String>list2 =new ControlledArrayList<>(false );assertTrue (list2 .isModifiable());// Standard methods can modify - Returns:
true if this list is modifiable through standardListinterface methods.
-
iterator
-
listIterator
- Specified by:
listIteratorin interfaceList<E>- Overrides:
listIteratorin classArrayList<E>
-
listIterator
- Specified by:
listIteratorin interfaceList<E>- Overrides:
listIteratorin classArrayList<E>
-
overrideAdd
Same asadd(Object)but bypasses the modifiable flag.This method allows you to add an element to the list even when it's marked as unmodifiable. It's intended for use by trusted internal code that needs to modify the list regardless of its modifiable state.
Example:
ControlledArrayList<String>
list =new ControlledArrayList<>(true );list .add("x" );// Throws UnsupportedOperationException list .overrideAdd("x" );// Works! - Parameters:
element- Element to be added to this list.- Returns:
true (as specified byCollection.add(Object)).
-
overrideAdd
Same asadd(int, Object)but bypasses the modifiable flag.- Parameters:
index- Index of the element to replace.element- Element to be stored at the specified position.
-
overrideAddAll
Same asaddAll(Collection)but bypasses the modifiable flag.- Parameters:
c- Collection containing elements to be added to this list.- Returns:
true if this list changed as a result of the call.
-
overrideAddAll
Same asaddAll(int,Collection)but bypasses the modifiable flag.- Parameters:
index- Index at which to insert the first element from the specified collection.c- Collection containing elements to be added to this list.- Returns:
true if this list changed as a result of the call.
-
overrideClear
Same asclear()but bypasses the modifiable flag. -
overrideIterator
Same asiterator()but bypasses the modifiable flag.- Returns:
- An iterator over the elements in this list in proper sequence.
-
overrideListIterator
Same aslistIterator()but bypasses the modifiable flag.- Parameters:
index- Index of the first element to be returned from the list iterator.- Returns:
- A list iterator over the elements in this list (in proper sequence), starting at the specified position in the list.
-
overrideRemove
Same asremove(int)but bypasses the modifiable flag.- Parameters:
index- Index of the element to remove.- Returns:
- The element that was removed from the list.
-
overrideRemove
Same asremove(Object)but bypasses the modifiable flag.- Parameters:
o- Element to be removed from this list, if present.- Returns:
true if this list contained the specified element.
-
overrideRemoveAll
Same asremoveAll(Collection)but bypasses the modifiable flag.- Parameters:
c- Collection containing elements to be removed from this list.- Returns:
true if this list changed as a result of the call.
-
overrideRemoveIf
Same asremoveIf(Predicate)but bypasses the modifiable flag.- Parameters:
filter- A predicate which returns true for elements to be removed.- Returns:
true if any elements were removed.
-
overrideReplaceAll
Same asreplaceAll(UnaryOperator)but bypasses the modifiable flag.- Parameters:
operator- The operator to apply to each element.
-
overrideRetainAll
Same asretainAll(Collection)but bypasses the modifiable flag.- Parameters:
c- Collection containing elements to be retained in this list.- Returns:
true if this list changed as a result of the call.
-
overrideSet
Same asset(int, Object)but bypasses the modifiable flag.- Parameters:
index- Index of the element to replace.element- Element to be stored at the specified position.- Returns:
- The element previously at the specified position.
-
overrideSort
Same asoverrideSort(Comparator)but bypasses the modifiable flag.- Parameters:
c- The Comparator used to compare list elements. A null value indicates that the elements' natural ordering should be used.
-
remove
-
remove
-
removeAll
-
removeIf
-
replaceAll
- Specified by:
replaceAllin interfaceList<E>- Overrides:
replaceAllin classArrayList<E>
-
retainAll
-
set
-
setUnmodifiable
Makes this list unmodifiable through standardListinterface methods.After calling this method, all standard modification methods (e.g.,
add(Object),remove(int)) will throwUnsupportedOperationException. However, the override methods (e.g.,overrideAdd(Object)) can still be used to modify the list.Example:
ControlledArrayList<String>
list =new ControlledArrayList<>(false );list .add("a" );// Works list .setUnmodifiable();list .add("b" );// Throws UnsupportedOperationException list .overrideAdd("b" );// Still works - Returns:
- This object for method chaining.
-
sort
-
subList
-
assertModifiable
Throws anUnsupportedOperationExceptionif the unmodifiable flag is set on this list.This method is called by all standard
Listinterface modification methods to enforce the unmodifiable restriction. Override methods bypass this check.- Throws:
UnsupportedOperationException- if the list is unmodifiable.
-