ChunkedArrayList extends AbstractList<T> { @Override public boolean add(T e) { if (size == Integer.MAX_VALUE) { throw new RuntimeException("Can't add an additional element to the " + "list; list already has INT_MAX elements."); } if (lastChunk == null) { addChunk(initialChunkCapacity); } else if (lastChunk.size() >= lastChunkCapacity) { int newCapacity = lastChunkCapacity + (lastChunkCapacity >> 1); addChunk(Math.min(newCapacity, maxChunkSize)); } size++; return lastChunk.add(e); } ChunkedArrayList();  ChunkedArrayList(int initialChunkCapacity, int maxChunkSize); @Override Iterator<T> iterator(); @Override boolean add(T e); @Override void clear(); @Override boolean isEmpty(); @Override int size(); @Override T get(int idx);  }
@Test public void testPerformance() { String obj = "hello world"; final int numElems = 1000000; final int numTrials = 5; for (int trial = 0; trial < numTrials; trial++) { System.gc(); { ArrayList<String> arrayList = new ArrayList<String>(); StopWatch sw = new StopWatch(); sw.start(); for (int i = 0; i < numElems; i++) { arrayList.add(obj); } System.out.println(" ArrayList " + sw.now(TimeUnit.MILLISECONDS)); } System.gc(); { ChunkedArrayList<String> chunkedList = new ChunkedArrayList<String>(); StopWatch sw = new StopWatch(); sw.start(); for (int i = 0; i < numElems; i++) { chunkedList.add(obj); } System.out.println("ChunkedArrayList " + sw.now(TimeUnit.MILLISECONDS)); } } }