EvictingBoundedList implements Iterable<T>, Serializable { @Override public Iterator<T> iterator() { return new Iterator<T>() { int pos = 0; final long oldModCount = modCount; @Override public boolean hasNext() { return pos < count; } @Override public T next() { if (oldModCount != modCount) { throw new ConcurrentModificationException(); } if (pos < count) { return get(pos++); } else { throw new NoSuchElementException("Iterator exhausted."); } } @Override public void remove() { throw new UnsupportedOperationException("Read-only iterator"); } }; } EvictingBoundedList(int sizeLimit);  EvictingBoundedList(EvictingBoundedList<T> other);  EvictingBoundedList(int sizeLimit, T defaultElement); int size(); boolean isEmpty(); boolean add(T t); void clear(); T get(int index); int getSizeLimit(); T set(int index, T element); T getDefaultElement(); @Override Iterator<T> iterator(); EvictingBoundedList<R> map(Function<T, R> transform);  }
@Test public void testIterator() { int insertSize = 17; int boundSize = 5; Integer defaultElement = 4711; EvictingBoundedList<Integer> list = new EvictingBoundedList<>(boundSize, defaultElement); assertTrue(list.isEmpty()); for (int i = 0; i < insertSize; ++i) { list.add(i); } Iterator<Integer> iterator = list.iterator(); for (int i = 0; i < insertSize; ++i) { assertTrue(iterator.hasNext()); int exp = i < (insertSize - boundSize) ? defaultElement : i; int act = iterator.next(); assertEquals(exp, act); } assertFalse(iterator.hasNext()); try { iterator.next(); fail("Next on exhausted iterator did not trigger exception."); } catch (NoSuchElementException ignored) { } iterator = list.iterator(); assertTrue(iterator.hasNext()); iterator.next(); list.add(123); assertTrue(iterator.hasNext()); try { iterator.next(); fail("Concurrent modification not detected."); } catch (ConcurrentModificationException ignored) { } }