[COLLECTIONS-471] Added BoundedIterator.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1546220 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
59899e1c82
commit
ba8758326c
3
pom.xml
3
pom.xml
|
@ -384,6 +384,9 @@
|
||||||
<contributor>
|
<contributor>
|
||||||
<name>Leo Sutic</name>
|
<name>Leo Sutic</name>
|
||||||
</contributor>
|
</contributor>
|
||||||
|
<contributor>
|
||||||
|
<name>Radford Tam</name>
|
||||||
|
</contributor>
|
||||||
<contributor>
|
<contributor>
|
||||||
<name>Chris Tilden</name>
|
<name>Chris Tilden</name>
|
||||||
</contributor>
|
</contributor>
|
||||||
|
|
|
@ -22,8 +22,9 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<release version="4.0.1" date="TBD" description="">
|
<release version="4.0.1" date="TBD" description="">
|
||||||
<!-- <action issue="COLLECTIONS-XXX" dev="XXX" type="XXX">
|
<action issue="COLLECTIONS-471" dev="tn" type="add" due-to="Radford Tam">
|
||||||
</action> -->
|
Added new decorator "BoundedIterator".
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="4.0" date="2013-11-27" description="
|
<release version="4.0" date="2013-11-27" description="
|
||||||
This is a major release: It combines bug fixes, new features and
|
This is a major release: It combines bug fixes, new features and
|
||||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.collections4.iterators.ArrayIterator;
|
import org.apache.commons.collections4.iterators.ArrayIterator;
|
||||||
import org.apache.commons.collections4.iterators.ArrayListIterator;
|
import org.apache.commons.collections4.iterators.ArrayListIterator;
|
||||||
|
import org.apache.commons.collections4.iterators.BoundedIterator;
|
||||||
import org.apache.commons.collections4.iterators.CollatingIterator;
|
import org.apache.commons.collections4.iterators.CollatingIterator;
|
||||||
import org.apache.commons.collections4.iterators.EmptyIterator;
|
import org.apache.commons.collections4.iterators.EmptyIterator;
|
||||||
import org.apache.commons.collections4.iterators.EmptyListIterator;
|
import org.apache.commons.collections4.iterators.EmptyListIterator;
|
||||||
|
@ -432,6 +433,44 @@ public class IteratorUtils {
|
||||||
return new ArrayListIterator<E>(array, start, end);
|
return new ArrayListIterator<E>(array, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bounded
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Decorates the specified iterator to return at most the given number
|
||||||
|
* of elements.
|
||||||
|
*
|
||||||
|
* @param <E> the element type
|
||||||
|
* @param iterator the iterator to decorate
|
||||||
|
* @param max the maximum number of elements returned by this iterator
|
||||||
|
* @return a new bounded iterator
|
||||||
|
* @throws IllegalArgumentException if the iterator is null or either offset or max is negative
|
||||||
|
* @since 4.0.1
|
||||||
|
*/
|
||||||
|
public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator, long max) {
|
||||||
|
return BoundedIterator.boundedIterator(iterator, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the specified iterator to return at most the given number
|
||||||
|
* of elements, skipping all elements until the iterator reaches the
|
||||||
|
* position at {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* The iterator is immediately advanced until it reaches the position at
|
||||||
|
* {@code offset}, incurring O(n) time.
|
||||||
|
*
|
||||||
|
* @param <E> the element type
|
||||||
|
* @param iterator the iterator to decorate
|
||||||
|
* @param offset the index of the first element of the decorated iterator to return
|
||||||
|
* @param max the maximum number of elements returned by this iterator
|
||||||
|
* @return a new bounded iterator
|
||||||
|
* @throws IllegalArgumentException if the iterator is null or either offset or max is negative
|
||||||
|
* @since 4.0.1
|
||||||
|
*/
|
||||||
|
public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator,
|
||||||
|
long offset, long max) {
|
||||||
|
return BoundedIterator.boundedIterator(iterator, offset, max);
|
||||||
|
}
|
||||||
|
|
||||||
// Unmodifiable
|
// Unmodifiable
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with this
|
||||||
|
* work for additional information regarding copyright ownership. The ASF
|
||||||
|
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
|
||||||
|
* or agreed to in writing, software distributed under the License is
|
||||||
|
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the specific language
|
||||||
|
* governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.collections4.iterators;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates another iterator to return elements in a specific range.
|
||||||
|
* <p>
|
||||||
|
* The decorated iterator is bounded in the range [offset, offset+max).
|
||||||
|
* The {@code offset} corresponds to the position of the first element to
|
||||||
|
* be returned from the decorated iterator, and {@code max} is the maximum
|
||||||
|
* number of elements to be returned at most.
|
||||||
|
* <p>
|
||||||
|
* In case an offset parameter other than 0 is provided, the decorated
|
||||||
|
* iterator is immediately advanced to this position, skipping all elements
|
||||||
|
* before that position.
|
||||||
|
*
|
||||||
|
* @since 4.0.1
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class BoundedIterator<E> implements Iterator<E> {
|
||||||
|
|
||||||
|
/** The iterator being decorated. */
|
||||||
|
private final Iterator<? extends E> iterator;
|
||||||
|
|
||||||
|
/** The offset to bound the first element return */
|
||||||
|
private final long offset;
|
||||||
|
|
||||||
|
/** The max number of elements to return */
|
||||||
|
private final long max;
|
||||||
|
|
||||||
|
/** The position of the current element */
|
||||||
|
private long pos;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the specified iterator to return at most the given number
|
||||||
|
* of elements.
|
||||||
|
*
|
||||||
|
* @param <E> the element type
|
||||||
|
* @param iterator the iterator to decorate
|
||||||
|
* @param max the maximum number of elements returned by this iterator
|
||||||
|
* @return a new bounded iterator
|
||||||
|
* @throws IllegalArgumentException if the iterator is null or max is negative
|
||||||
|
*/
|
||||||
|
public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator,
|
||||||
|
final long max) {
|
||||||
|
return boundedIterator(iterator, 0, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the specified iterator to return at most the given number
|
||||||
|
* of elements, skipping all elements until the iterator reaches the position
|
||||||
|
* at {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* The iterator is immediately advanced until it reaches the position at {@code offset},
|
||||||
|
* incurring O(n) time.
|
||||||
|
*
|
||||||
|
* @param <E> the element type
|
||||||
|
* @param iterator the iterator to decorate
|
||||||
|
* @param offset the index of the first element of the decorated iterator to return
|
||||||
|
* @param max the maximum number of elements returned by this iterator
|
||||||
|
* @return a new bounded iterator
|
||||||
|
* @throws IllegalArgumentException if the iterator is null or either offset or max is negative
|
||||||
|
*/
|
||||||
|
public static <E> BoundedIterator<E> boundedIterator(final Iterator<? extends E> iterator,
|
||||||
|
final long offset, final long max) {
|
||||||
|
return new BoundedIterator<E>(iterator, 0, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the specified iterator to return at most the given number of elements,
|
||||||
|
* skipping all elements until the iterator reaches the position at {@code offset}.
|
||||||
|
* <p>
|
||||||
|
* The iterator is immediately advanced until it reaches the position at {@code offset},
|
||||||
|
* incurring O(n) time.
|
||||||
|
*
|
||||||
|
* @param iterator the iterator to be decorated
|
||||||
|
* @param offset the index of the first element of the decorated iterator to return
|
||||||
|
* @param max the maximum number of elements of the decorated iterator to return
|
||||||
|
* @throws IllegalArgumentException if iterator is null, or either offset or max is negative
|
||||||
|
*/
|
||||||
|
public BoundedIterator(final Iterator<? extends E> iterator, final long offset, final long max) {
|
||||||
|
if (iterator == null) {
|
||||||
|
throw new IllegalArgumentException("Iterator must not be null");
|
||||||
|
}
|
||||||
|
if (offset < 0) {
|
||||||
|
throw new IllegalArgumentException("Offset parameter must not be negative.");
|
||||||
|
}
|
||||||
|
if (max < 0) {
|
||||||
|
throw new IllegalArgumentException("Max parameter must not be negative.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.iterator = iterator;
|
||||||
|
this.offset = offset;
|
||||||
|
this.max = max;
|
||||||
|
pos = 0;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advances the underlying iterator to the beginning of the bounded range.
|
||||||
|
*/
|
||||||
|
private void init() {
|
||||||
|
while (pos < offset && iterator.hasNext()) {
|
||||||
|
iterator.next();
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
if (!checkBounds()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return iterator.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the iterator is still within its bounded range.
|
||||||
|
* @return {@code true} if the iterator is within its bounds, {@code false} otherwise
|
||||||
|
*/
|
||||||
|
private boolean checkBounds() {
|
||||||
|
if (pos - offset + 1 > max) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public E next() {
|
||||||
|
if (!checkBounds()) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
final E next = iterator.next();
|
||||||
|
pos++;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* In case an offset other than 0 was specified, the underlying iterator will be advanced
|
||||||
|
* to this position upon creation. A call to {@link #remove()} will still result in an
|
||||||
|
* {@link IllegalStateException} if no explicit call to {@link #next()} has been made prior
|
||||||
|
* to calling {@link #remove()}.
|
||||||
|
*/
|
||||||
|
public void remove() {
|
||||||
|
if (pos <= offset) {
|
||||||
|
throw new IllegalStateException("remove() can not be called before calling next()");
|
||||||
|
}
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with this
|
||||||
|
* work for additional information regarding copyright ownership. The ASF
|
||||||
|
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
|
||||||
|
* or agreed to in writing, software distributed under the License is
|
||||||
|
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the specific language
|
||||||
|
* governing permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.commons.collections4.iterators;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unit test to test the basic functions of {@link BoundedIterator}.
|
||||||
|
*
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class BoundedIteratorTest<E> extends AbstractIteratorTest<E> {
|
||||||
|
|
||||||
|
/** Test array of size 7 */
|
||||||
|
private String[] testArray = {
|
||||||
|
"a", "b", "c", "d", "e", "f", "g"
|
||||||
|
};
|
||||||
|
|
||||||
|
private List<E> testList;
|
||||||
|
|
||||||
|
public BoundedIteratorTest(final String testName) {
|
||||||
|
super(testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void setUp()
|
||||||
|
throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
testList = Arrays.asList((E[]) testArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<E> makeEmptyIterator() {
|
||||||
|
return BoundedIterator.boundedIterator(Collections.<E>emptyList().iterator(), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<E> makeObject() {
|
||||||
|
return BoundedIterator.boundedIterator(new ArrayList<E>(testList).iterator(), 1, testList.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Tests ---------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a decorated iterator bounded such that the first element returned is
|
||||||
|
* at an index greater its first element, and the last element returned is
|
||||||
|
* at an index less than its last element.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBounded() {
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testList.iterator(), 2, 4);
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("c", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("d", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("e", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("f", iter.next());
|
||||||
|
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a decorated iterator bounded such that the <code>offset</code> is
|
||||||
|
* zero and the <code>max</code> is its size, in that the BoundedIterator
|
||||||
|
* should return all the same elements as its decorated iterator.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSameAsDecorated() {
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testList.iterator(), 0,
|
||||||
|
testList.size());
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("a", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("b", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("c", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("d", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("e", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("f", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("g", iter.next());
|
||||||
|
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a decorated iterator bounded to a <code>max</code> of 0. The
|
||||||
|
* BoundedIterator should behave as if there are no more elements to return,
|
||||||
|
* since it is technically an empty iterator.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEmptyBounded() {
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testList.iterator(), 3, 0);
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the case if a negative <code>offset</code> is passed to the
|
||||||
|
* constructor. {@link IllegalArgumentException} is expected.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testNegativeOffset() {
|
||||||
|
try {
|
||||||
|
new BoundedIterator<E>(testList.iterator(), -1, 4);
|
||||||
|
fail("Expected IllegalArgumentException.");
|
||||||
|
} catch (IllegalArgumentException iae) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the case if a negative <code>max</code> is passed to the
|
||||||
|
* constructor. {@link IllegalArgumentException} is expected.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testNegativeMax() {
|
||||||
|
try {
|
||||||
|
new BoundedIterator<E>(testList.iterator(), 3, -1);
|
||||||
|
fail("Expected IllegalArgumentException.");
|
||||||
|
} catch (IllegalArgumentException iae) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the case if the <code>offset</code> passed to the constructor is
|
||||||
|
* greater than the decorated iterator's size. The BoundedIterator should
|
||||||
|
* behave as if there are no more elements to return.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testOffsetGreaterThanSize() {
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testList.iterator(), 10, 4);
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the case if the <code>max</code> passed to the constructor is
|
||||||
|
* greater than the size of the decorated iterator. The last element
|
||||||
|
* returned should be the same as the last element of the decorated
|
||||||
|
* iterator.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testMaxGreaterThanSize() {
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testList.iterator(), 1, 10);
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("b", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("c", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("d", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("e", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("f", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("g", iter.next());
|
||||||
|
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the <code>remove()</code> method being called without
|
||||||
|
* <code>next()</code> being called first.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveWithoutCallingNext() {
|
||||||
|
List<E> testListCopy = new ArrayList<E>(testList);
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testListCopy.iterator(), 1, 5);
|
||||||
|
|
||||||
|
try {
|
||||||
|
iter.remove();
|
||||||
|
fail("Expected IllegalStateException.");
|
||||||
|
} catch (IllegalStateException ise) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the <code>remove()</code> method being called twice without calling
|
||||||
|
* <code>next()</code> in between.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveCalledTwice() {
|
||||||
|
List<E> testListCopy = new ArrayList<E>(testList);
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testListCopy.iterator(), 1, 5);
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("b", iter.next());
|
||||||
|
iter.remove();
|
||||||
|
|
||||||
|
try {
|
||||||
|
iter.remove();
|
||||||
|
fail("Expected IllegalStateException.");
|
||||||
|
} catch (IllegalStateException ise) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test removing the first element. Verify that the element is removed from
|
||||||
|
* the underlying collection.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveFirst() {
|
||||||
|
List<E> testListCopy = new ArrayList<E>(testList);
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testListCopy.iterator(), 1, 5);
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("b", iter.next());
|
||||||
|
|
||||||
|
iter.remove();
|
||||||
|
assertFalse(testListCopy.contains("b"));
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("c", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("d", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("e", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("f", iter.next());
|
||||||
|
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test removing an element in the middle of the iterator. Verify that the
|
||||||
|
* element is removed from the underlying collection.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveMiddle() {
|
||||||
|
List<E> testListCopy = new ArrayList<E>(testList);
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testListCopy.iterator(), 1, 5);
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("b", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("c", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("d", iter.next());
|
||||||
|
|
||||||
|
iter.remove();
|
||||||
|
assertFalse(testListCopy.contains("d"));
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("e", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("f", iter.next());
|
||||||
|
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test removing the last element. Verify that the element is removed from
|
||||||
|
* the underlying collection.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveLast() {
|
||||||
|
List<E> testListCopy = new ArrayList<E>(testList);
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(testListCopy.iterator(), 1, 5);
|
||||||
|
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("b", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("c", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("d", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("e", iter.next());
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("f", iter.next());
|
||||||
|
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
|
||||||
|
iter.remove();
|
||||||
|
assertFalse(testListCopy.contains("f"));
|
||||||
|
|
||||||
|
assertFalse(iter.hasNext());
|
||||||
|
try {
|
||||||
|
iter.next();
|
||||||
|
fail("Expected NoSuchElementException.");
|
||||||
|
} catch (NoSuchElementException nsee) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the case if the decorated iterator does not support the
|
||||||
|
* <code>remove()</code> method and throws an {@link UnsupportedOperationException}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testRemoveUnsupported() {
|
||||||
|
Iterator<E> mockIterator = new AbstractIteratorDecorator<E>(testList.iterator()) {
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Iterator<E> iter = new BoundedIterator<E>(mockIterator, 1, 5);
|
||||||
|
assertTrue(iter.hasNext());
|
||||||
|
assertEquals("b", iter.next());
|
||||||
|
try {
|
||||||
|
iter.remove();
|
||||||
|
fail("Expected UnsupportedOperationException.");
|
||||||
|
} catch (UnsupportedOperationException usoe) { /* Success case */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue