Reputation: 1149
Thinking in java says:
To create a read-only List from AbstractList, you must implements get() and size().
It confused me, the code is below:
public class CountingIntegerList
extends AbstractList<Integer> {
private int size;
public CountingIntegerList(int size) {
this.size = size < 0 ? 0 : size;
}
public Integer get(int index) {
return Integer.valueOf(index);
}
public int size() { return size; }
public static void main(String[] args) {
List list = new CountingIntegerList(30);
}
}
Is list a read-only List? Why?
Ok, the answer is yes since I extend AbstractList
and it throw UnsupportedOperationException
if set
or and
is called. If I want to get a unmodifiableList, Collections.unmodifiableList()
is a good choice. But remember, both of them are not deeply immutable:
List<StringBuilder> list = new ArrayList<StringBuilder>();
StringBuilder sb = new StringBuilder();
sb.append("hello");
list.add(sb);
System.out.println(list);
list = Collections.unmodifiableList(list);
sb.append("world");
System.out.println(list);
There is a flyweight pattern
in CountingIntegerList
. because everytime get()
is called,it get caches from Integer, the source code of valueOf()
:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Is is right?
Upvotes: 1
Views: 1589
Reputation: 1088
It's read-only (even immutable) because add
will throw an UnsupportedOperationException
as will remove
.
AbstractList
handles all the work of creating iterators,
computing hashcodes and equality for you. It's very helpful.
It's completely unnecessary to wrap in unmodifiableList
.
Later you ask whether AbstractList
is used mainly to create unmodifiable lists. Actually it is used to create any kind of random-access list. In my course in data structures, we use abstract classes such as this to save most of the work of implementing a list class. Even the Collection
interface has 13 methods, all but two of which are implements by AbstractCollection
.
There is the related class AbstractSequentialList
that helps create lists that are not random access (such as linked lists).
Upvotes: 5
Reputation: 120858
This is tricky a bit. The list can not change and/or the elements also? ;)
StringBuilder builder = new StringBuilder();
builder.append("Hello");
List<StringBuilder> list = new ArrayList<StringBuilder>();
list.add(builder);
Collection<StringBuilder> canNotChange = Collections.unmodifiableCollection(list);
builder.append(" World");
System.out.println(canNotChange.iterator().next());
Upvotes: 0
Reputation: 2644
you could wrap your List in an UnmodifiableList
List readOnlyList = Collections.unmodifiableList(yourList)
Upvotes: 4
Reputation: 12843
Pass the ArrayList into Collections.unmodifiableList()
Returns an unmodifiable view of the specified list. This method allows modules to provide users with "read-only" access to internal lists. Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list, whether direct or via its iterator, result in an UnsupportedOperationException. The returned list will be serializable if the specified list is serializable. Similarly, the returned list will implement RandomAccess if the specified list does.
Upvotes: 1