Bug 34267: IteratorChain.remove() in combination with FilterIterator

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@170581 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
James W. Carman 2005-05-17 11:56:36 +00:00
parent d65e2938fc
commit 51c9effb79
2 changed files with 56 additions and 19 deletions

View File

@ -40,10 +40,10 @@ import org.apache.commons.collections.list.UnmodifiableList;
* <p> * <p>
* NOTE: As from version 3.0, the IteratorChain may contain no * NOTE: As from version 3.0, the IteratorChain may contain no
* iterators. In this case the class will function as an empty iterator. * iterators. In this case the class will function as an empty iterator.
* *
* @since Commons Collections 2.1 * @since Commons Collections 2.1
* @version $Revision$ $Date$ * @version $Revision$ $Date$
* *
* @author Morgan Delagrange * @author Morgan Delagrange
* @author Stephen Colebourne * @author Stephen Colebourne
*/ */
@ -80,7 +80,7 @@ public class IteratorChain implements Iterator {
/** /**
* Construct an IteratorChain with a single Iterator. * Construct an IteratorChain with a single Iterator.
* *
* @param iterator first Iterator in the IteratorChain * @param iterator first Iterator in the IteratorChain
* @throws NullPointerException if the iterator is null * @throws NullPointerException if the iterator is null
*/ */
@ -135,8 +135,8 @@ public class IteratorChain implements Iterator {
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
/** /**
* Add an Iterator to the end of the chain * Add an Iterator to the end of the chain
* *
* @param iterator Iterator to add * @param iterator Iterator to add
* @throws IllegalStateException if I've already started iterating * @throws IllegalStateException if I've already started iterating
* @throws NullPointerException if the iterator is null * @throws NullPointerException if the iterator is null
@ -150,8 +150,8 @@ public class IteratorChain implements Iterator {
} }
/** /**
* Set the Iterator at the given index * Set the Iterator at the given index
* *
* @param index index of the Iterator to replace * @param index index of the Iterator to replace
* @param iterator Iterator to place at the given index * @param iterator Iterator to place at the given index
* @throws IndexOutOfBoundsException if index &lt; 0 or index &gt; size() * @throws IndexOutOfBoundsException if index &lt; 0 or index &gt; size()
@ -168,7 +168,7 @@ public class IteratorChain implements Iterator {
/** /**
* Get the list of Iterators (unmodifiable) * Get the list of Iterators (unmodifiable)
* *
* @return the unmodifiable list of iterators added * @return the unmodifiable list of iterators added
*/ */
public List getIterators() { public List getIterators() {
@ -177,7 +177,7 @@ public class IteratorChain implements Iterator {
/** /**
* Number of Iterators in the current IteratorChain. * Number of Iterators in the current IteratorChain.
* *
* @return Iterator count * @return Iterator count
*/ */
public int size() { public int size() {
@ -188,8 +188,8 @@ public class IteratorChain implements Iterator {
* Determine if modifications can still be made to the IteratorChain. * Determine if modifications can still be made to the IteratorChain.
* IteratorChains cannot be modified once they have executed a method * IteratorChains cannot be modified once they have executed a method
* from the Iterator interface. * from the Iterator interface.
* *
* @return true if IteratorChain cannot be modified, false if it can * @return true if IteratorChain cannot be modified, false if it can
*/ */
public boolean isLocked() { public boolean isLocked() {
return isLocked; return isLocked;
@ -239,7 +239,7 @@ public class IteratorChain implements Iterator {
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
/** /**
* Return true if any Iterator in the IteratorChain has a remaining element. * Return true if any Iterator in the IteratorChain has a remaining element.
* *
* @return true if elements remain * @return true if elements remain
*/ */
public boolean hasNext() { public boolean hasNext() {
@ -252,7 +252,7 @@ public class IteratorChain implements Iterator {
/** /**
* Returns the next Object of the current Iterator * Returns the next Object of the current Iterator
* *
* @return Object from the current Iterator * @return Object from the current Iterator
* @throws java.util.NoSuchElementException if all the Iterators are exhausted * @throws java.util.NoSuchElementException if all the Iterators are exhausted
*/ */
@ -265,13 +265,13 @@ public class IteratorChain implements Iterator {
} }
/** /**
* Removes from the underlying collection the last element * Removes from the underlying collection the last element
* returned by the Iterator. As with next() and hasNext(), * returned by the Iterator. As with next() and hasNext(),
* this method calls remove() on the underlying Iterator. * this method calls remove() on the underlying Iterator.
* Therefore, this method may throw an * Therefore, this method may throw an
* UnsupportedOperationException if the underlying * UnsupportedOperationException if the underlying
* Iterator does not support this method. * Iterator does not support this method.
* *
* @throws UnsupportedOperationException * @throws UnsupportedOperationException
* if the remove operator is not supported by the underlying Iterator * if the remove operator is not supported by the underlying Iterator
* @throws IllegalStateException * @throws IllegalStateException
@ -280,8 +280,9 @@ public class IteratorChain implements Iterator {
*/ */
public void remove() { public void remove() {
lockChain(); lockChain();
updateCurrentIterator(); if( currentIterator == null ) {
updateCurrentIterator();
}
lastUsedIterator.remove(); lastUsedIterator.remove();
} }

View File

@ -19,9 +19,13 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.LinkedList;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.apache.commons.collections.PredicateUtils;
import org.apache.commons.collections.IteratorUtils;
import org.apache.commons.collections.Predicate;
/** /**
* Tests the IteratorChain class. * Tests the IteratorChain class.
@ -95,6 +99,38 @@ public class TestIteratorChain extends AbstractTestIterator {
} }
} }
public void testRemoveFromFilteredIterator() {
final Predicate myPredicate = new Predicate() {
public boolean evaluate( Object object ) {
Integer i = (Integer) object;
if (i.compareTo(new Integer(4)) < 0)
return true;
return false;
}
};
List list1 = new ArrayList();
List list2 = new ArrayList();
list1.add(new Integer(1));
list1.add(new Integer(2));
list2.add(new Integer(3));
list2.add(new Integer(4)); // will be ignored by the predicate
Iterator it1 = IteratorUtils.filteredIterator(list1.iterator(), myPredicate );
Iterator it2 = IteratorUtils.filteredIterator(list2.iterator(), myPredicate );
Iterator it = IteratorUtils.chainedIterator(it1, it2);
while (it.hasNext()) {
it.next();
it.remove();
}
assertEquals( 0, list1.size() );
assertEquals( 1, list2.size() );
}
public void testRemove() { public void testRemove() {
Iterator iter = (Iterator) makeFullIterator(); Iterator iter = (Iterator) makeFullIterator();