ConcatenationIterator implements Iterator<T> { @Override public boolean hasNext() { for (Iterator<T> inputIterator : inputIterators) { if (inputIterator.hasNext()) { return true; } } return false; } ConcatenationIterator(Iterator<T>... inputIterators); @Override boolean hasNext(); @Override T next(); @Override void remove();  }
@Test public void testHasNextReturnsFalseWhenAllInputIteratorAreEmpty() { Iterator<Object> emptyIterator = Arrays.asList().iterator(); Iterator<Object> emptyIterator2 = Arrays.asList().iterator(); ConcatenationIterator<Object> concatenationIterator = new ConcatenationIterator<>(emptyIterator, emptyIterator2); boolean hasNext = concatenationIterator.hasNext(); assertFalse(hasNext); }
@Test public void testHasNextReturnsTrueWhenAnyInputIteratorHasRemainingElements() { Iterator<Object> emptyIterator = Arrays.asList().iterator(); Iterator<Object> filledIterator = Arrays.<Object>asList(1, 2, 3).iterator(); Iterator<Object> emptyIterator2 = Arrays.asList().iterator(); ConcatenationIterator<Object> concatenationIterator = new ConcatenationIterator<>(emptyIterator, filledIterator, emptyIterator2); boolean hasNext = concatenationIterator.hasNext(); assertTrue(hasNext); }