import java.util.AbstractCollection; import java.util.Collection; import java.util.Iterator; /** * @author Matt Chun-Lum * */ public class ChunkList<E> extends AbstractCollection<E> implements Collection<E> { private Chunk head = null, tail = null; private int size = 0; @Override public boolean add(E e) { if(tail == null || tail.isFull()) addChunk(); return tail.add(e); } @Override public Iterator<E> iterator() { return new ChunkIterator(); } @Override public int size() { return size; } // ------------------- Private ------------------- // /* * adds a chunk to the list. If the ChunkList is empty (the tail is null), adds the * chunk as the initial element in the list. */ private void addChunk() { Chunk chunk = new Chunk(); if(tail == null) { tail = chunk; head = chunk; } else { tail.next = chunk; tail = chunk; } } /* * private inner class for iterator */ private class ChunkIterator implements Iterator<E> { private int index = 0; private Chunk next = head; private Chunk previous = null; // returns whether or not the iterator has a next element public boolean hasNext() { if(next != null && (next.next != null || index < next.size())) return true; return false; } // returns the next element public E next() { if(index >= next.size()) { previous = next; next = next.next; index = 0; } return next.data[index++]; } // removes the last element returned by the iterator public void remove() { next.remove(--index); if(next.isEmpty()) { if(previous == null) head = next.next; else previous.next = next.next; Chunk temp = next.next; next = null; next = temp; index = 0; if(next == null) tail = previous; else if(next.next == null) tail = next; } } } /* * private inner class Chunk stores the elements for the Chunk list */ private class Chunk { private static final int ARRAY_SIZE = 8; E[] data; int chunkSize; Chunk next; Chunk() { data = (E[]) new Object[ARRAY_SIZE]; chunkSize = 0; next = null; } /* * Adds an element to the internal array. Returns true if the element was * added, false if the internal array is full. */ boolean add(E e) { if(!isFull()) { size++; data[chunkSize++] = e; return true; } return false; } /* * returns true if the internal array is full */ boolean isFull() { return chunkSize == ARRAY_SIZE; } /* * returns true if the internal array is empty */ boolean isEmpty() { return chunkSize == 0; } /* * returns the size of the chunk */ int size() { return chunkSize; } /* * removes the element at the specified index and shifts the contents of the * array if necessary */ void remove(int index) { data[index] = null; int i; for(i = index; i < chunkSize-1; i++) data[i] = data[i + 1]; data[i] = null; chunkSize--; size--; } /* * removes the element, if it exists, from the array. * * not called in this implementation (it would be slower) */ void remove(E e) { for(int i = 0; i < chunkSize; i++) if(e.equals(data[i])) { remove(i); break; } } } }