📄 collatingiterator.java
字号:
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed 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.collections.iterators;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.ArrayList;
import java.util.BitSet;
/**
* Provides an ordered iteration over the elements contained in
* a collection of ordered {@link Iterator}s. In other words,
* given two ordered {@link Iterator}s <code>A</code> and <code>B</code>,
* my {@link #next} method will return the lesser of
* <code>A.next()</code> and <code>B.next()</code>.
*
* @since 2.1
* @author Rodney Waldhoff
* @author <a href="mailto:scolebourne@joda.org">Stephen Colebourne</a>
* @version $Revision: 1.3.2.1 $ $Date: 2004/05/22 12:14:04 $
*/
public class CollatingIterator implements Iterator {
/** My {@link Comparator}. */
private Comparator comparator = null;
/** My list of {@link Iterator}s. */
private ArrayList iterators = null;
/** {@link Iterator#next Next} objects peeked from each iterator. */
private ArrayList values = null;
/** Whether or not each {@link #values} element has been set. */
private BitSet valueSet = null;
/** Index of the {@link #iterators iterator} from whom the last returned value was obtained. */
private int lastReturned = -1;
// Constructors
// -------------------------------------------------------------------
/**
* Constructs a new <Code>CollatingIterator</Code>. Natural sort order
* will be used, and child iterators will have to be manually added
* using the {@link #addIterator(Iterator)} method.
*/
public CollatingIterator() {
this(null,2);
}
/**
* Constructs a new <Code>CollatingIterator</Code> that will used the
* specified comparator for ordering. Child iterators will have to be
* manually added using the {@link #addIterator(Iterator)} method.
*
* @param comp the comparator to use for ordering, or <Code>null</Code>
* to use natural sort order
*/
public CollatingIterator(Comparator comp) {
this(comp,2);
}
/**
* Constructs a new <Code>CollatingIterator</Code> that will used the
* specified comparator for ordering and have the specified initial
* capacity. Child iterators will have to be
* manually added using the {@link #addIterator(Iterator)} method.
*
* @param comp the comparator to use for ordering, or <Code>null</Code>
* to use natural sort order
* @param initIterCapacity the initial capacity for the internal list
* of child iterators
*/
public CollatingIterator(Comparator comp, int initIterCapacity) {
iterators = new ArrayList(initIterCapacity);
setComparator(comp);
}
/**
* Constructs a new <Code>CollatingIterator</Code> that will use the
* specified comparator to provide ordered iteration over the two
* given iterators.
*
* @param comp the comparator to use to sort, or null to use natural
* sort order
* @param a the first child ordered iterator
* @param b the second child ordered iterator
* @throws NullPointerException if either iterator is null
*/
public CollatingIterator(Comparator comp, Iterator a, Iterator b) {
this(comp,2);
addIterator(a);
addIterator(b);
}
/**
* Constructs a new <Code>CollatingIterator</Code> that will use the
* specified comparator to provide ordered iteration over the array
* of iterators.
*
* @param comp the comparator to use to sort, or null to use natural
* sort order
* @param iterators the array of iterators
* @throws NullPointerException if iterators array is or contains null
*/
public CollatingIterator(Comparator comp, Iterator[] iterators) {
this(comp, iterators.length);
for (int i = 0; i < iterators.length; i++) {
addIterator(iterators[i]);
}
}
/**
* Constructs a new <Code>CollatingIterator</Code> that will use the
* specified comparator to provide ordered iteration over the collection
* of iterators.
*
* @param comp the comparator to use to sort, or null to use natural
* sort order
* @param iterators the collection of iterators
* @throws NullPointerException if the iterators collection is or contains null
* @throws ClassCastException if the iterators collection contains an
* element that's not an {@link Iterator}
*/
public CollatingIterator(Comparator comp, Collection iterators) {
this(comp, iterators.size());
for (Iterator it = iterators.iterator(); it.hasNext();) {
Iterator item = (Iterator) it.next();
addIterator(item);
}
}
// Public Methods
// -------------------------------------------------------------------
/**
* Add the given {@link Iterator} to my collection to collate.
* @throws IllegalStateException if I've already started iterating
* @throws NullPointerException if the iterator is null
*/
public void addIterator(Iterator iterator) {
checkNotStarted();
if (iterator == null) {
throw new NullPointerException("Iterator must not be null");
}
iterators.add(iterator);
}
/**
* Set the Iterator at the given index
*
* @param index index of the Iterator to replace
* @param iterator Iterator to place at the given index
* @throws IndexOutOfBoundsException if index < 0 or index > size()
* @throws IllegalStateException if I've already started iterating
* @throws NullPointerException if the iterator is null
*/
public void setIterator(int index, Iterator iterator) throws IndexOutOfBoundsException {
checkNotStarted();
if (iterator == null) {
throw new NullPointerException("Iterator must not be null");
}
iterators.set(index, iterator);
}
/**
* Get the list of Iterators (unmodifiable)
*
* @return the unmodifiable list of iterators added
*/
public List getIterators() {
return Collections.unmodifiableList(iterators);
}
/**
* Set the {@link Comparator} by which I collate.
* @throws IllegalStateException if I've already started iterating
*/
public void setComparator(Comparator comp) {
checkNotStarted();
comparator = comp;
}
/**
* Get the {@link Comparator} by which I collate.
*/
public Comparator getComparator() {
return comparator;
}
// Iterator Methods
// -------------------------------------------------------------------
/**
* Returns <Code>true</Code> if any child iterator has remaining elements.
*
* @return true if this iterator has remaining elements
*/
public boolean hasNext() {
start();
return anyValueSet(valueSet) || anyHasNext(iterators);
}
/**
* Returns the next ordered element from a child iterator.
*
* @return the next ordered element
* @throws NoSuchElementException if no child iterator has any more
* elements
*/
public Object next() throws NoSuchElementException {
if(!hasNext()) {
throw new NoSuchElementException();
} else {
int leastIndex = least();
if(leastIndex == -1) {
throw new NoSuchElementException();
} else {
Object val = values.get(leastIndex);
clear(leastIndex);
lastReturned = leastIndex;
return val;
}
}
}
/**
* Removes the last returned element from the child iterator that
* produced it.
*
* @throws IllegalStateException if there is no last returned element,
* or if the last returned element has already been removed
*/
public void remove() {
if(-1 == lastReturned) {
throw new NoSuchElementException("No value has been returned yet.");
} else {
Iterator iter = (Iterator)(iterators.get(lastReturned));
iter.remove();
}
}
// Private Methods
// -------------------------------------------------------------------
/** Initialize my collating state if it hasn't been already. */
private void start() {
if(null == values) {
values = new ArrayList(iterators.size());
valueSet = new BitSet(iterators.size());
for(int i=0;i<iterators.size();i++) {
values.add(null);
valueSet.clear(i);
}
}
}
/**
* Set the {@link #values} and {@link #valueSet} attributes
* at position <i>i</i> to the next value of the
* {@link #iterators iterator} at position <i>i</i>, or
* clear them if the <i>i</i><sup>th</sup> iterator
* has no next value.
*
* @return <tt>false</tt> iff there was no value to set
*/
private boolean set(int i) {
Iterator iter = (Iterator)(iterators.get(i));
if(iter.hasNext()) {
values.set(i,iter.next());
valueSet.set(i);
return true;
} else {
values.set(i,null);
valueSet.clear(i);
return false;
}
}
/**
* Clear the {@link #values} and {@link #valueSet} attributes
* at position <i>i</i>.
*/
private void clear(int i) {
values.set(i,null);
valueSet.clear(i);
}
/**
* Throw {@link IllegalStateException} iff I've been {@link #start started}.
* @throws IllegalStateException iff I've been {@link #start started}
*/
private void checkNotStarted() throws IllegalStateException {
if (null != values) {
throw new IllegalStateException("Can't do that after next or hasNext has been called.");
}
}
/**
* Returns the index of the least element in {@link #values},
* {@link #set(int) setting} any uninitialized values.
*/
private int least() throws IllegalStateException {
int leastIndex = -1;
Object leastObject = null;
for(int i=0;i<values.size();i++) {
if(!valueSet.get(i)) {
set(i);
}
if(valueSet.get(i)) {
if(leastIndex == -1) {
leastIndex = i;
leastObject = values.get(i);
} else {
Object curObject = values.get(i);
if(comparator.compare(curObject,leastObject) < 0) {
leastObject = curObject;
leastIndex = i;
}
}
}
}
return leastIndex;
}
/**
* Returns <code>true</code> iff any bit in the given set is
* <code>true</code>.
*/
private boolean anyValueSet(BitSet set) {
for(int i=0;i<set.size();i++) {
if(set.get(i)) {
return true;
}
}
return false;
}
/**
* Returns <code>true</code> iff any {@link Iterator}
* in the given list has a next value.
*/
private boolean anyHasNext(ArrayList iters) {
for(int i=0;i<iters.size();i++) {
Iterator iter = (Iterator)iters.get(i);
if(iter.hasNext()) {
return true;
}
}
return false;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -