As I wrote on SO, I need an ArrayList-like structure allowing just the following operations
get(int index)
add(E element)
set(int index, E element)
iterator()
while supporting iterations concurrent with modifications. While I'm waiting for something better, I tried it myself. It was a bit harder than expected, so I used synchronization, which made it easy again. I'm linking to the full code and the test and showing here the relevant part (i.e., everything but the imports).
/**
* A data structure implementing a tiny subset of List operations and allowing concurrent access.
*
* See http://stackoverflow.com/q/26424030/581205 for requirements.
*/
public class ConcurrentIterable<E> implements Iterable<E> {
class MyIterator extends UnmodifiableIterator<E> {
@Override public boolean hasNext() {
return index < size();
}
@Override public E next() {
try {
return get(index++); // Safe as the array never shrinks.
} catch (final IndexOutOfBoundsException e) {
// This is hacky, but better than checking the size upfront, as the size may change.
throw new NoSuchElementException();
}
}
private int index;
}
/**
* The returned iterator may or may not see the changes made after its creation.
* The only guarantee in case of concurrent modifications is is that
* it sees no garbage provided that the items are immutable.
*/
@Override public Iterator<E> iterator() {
return new MyIterator();
}
public synchronized int size() {
return size;
}
@SuppressWarnings("unchecked")
public synchronized E get(int index) {
checkElementIndex(index, size);
return (E) data[index];
}
public synchronized void add(E element) {
if (data.length == size) grow();
data[size++] = element;
}
public synchronized void set(int index, E element) {
checkElementIndex(index, size);
data[index] = element;
}
private void grow() {
data = Arrays.copyOf(data, newSize(data.length));
}
private static int newSize(int oldSize) {
int result = oldSize + (oldSize>>3) + 4; // Grow by about 1/8 only.
if (result-MAX_ARRAY_SIZE > 0) result = MAX_ARRAY_SIZE; // Handle overflow.
if (result<=oldSize) throw new OutOfMemoryError();
return result;
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // See ArrayList.
private int size;
private Object[] data = new Object[4];
}
I'm aware that it's incompatible with the Collection
or List
interfaces, but it's not meant to be general use class (though it may change). I need no additional constructors or other features.
Concerning spacing and single line conditional statements... yes, I know, I just don't care (my own conventions differ slightly).
I'll probably try to re-implement this without synchronization as a challenge.