ConcatenationIterator implements Iterator<T> { @Override public T next() { for (Iterator<T> inputIterator : inputIterators) { if (inputIterator.hasNext()) { return inputIterator.next(); } } throw new NoSuchElementException("No elements left in concatenated iterator."); } ConcatenationIterator(Iterator<T>... inputIterators); @Override boolean hasNext(); @Override T next(); @Override void remove();  }
@Test public void testNextAdvancesTheUnderlyingIterator() { Iterator<Object> iterator = Arrays.<Object>asList(1, 2, 3).iterator(); ConcatenationIterator<Object> concatenatedIterator = new ConcatenationIterator<>(iterator); Object firstElement = concatenatedIterator.next(); Object secondElement = concatenatedIterator.next(); assertThat(firstElement, is(not(secondElement))); }
@Test public void testNextReturnsTheFirstElementOfTheFirstNonEmptyIterator() { Iterator<Object> emptyIterator = Arrays.asList().iterator(); Iterator<Object> nonEmptyIterator = Arrays.<Object>asList(1, 2).iterator(); Iterator<Object> anotherNonEmptyIterator = Arrays.<Object>asList(3, 4).iterator(); ConcatenationIterator<Object> concatenatedIterator = new ConcatenationIterator<>(emptyIterator, nonEmptyIterator, anotherNonEmptyIterator); Object firstElement = concatenatedIterator.next(); assertThat(firstElement, CoreMatchers.<Object>is(1)); }
@Test(expected = NoSuchElementException.class) public void testNextThrowsExceptionWhenAllIteratorsAreEmpty() { Iterator<Object> emptyIterator = Arrays.asList().iterator(); Iterator<Object> emptyIterator2 = Arrays.asList().iterator(); ConcatenationIterator<Object> concatenatedIterator = new ConcatenationIterator<>(emptyIterator, emptyIterator2); concatenatedIterator.next(); }