Add Buffer implementations, utilities, and tests.
BoundedFifoBuffer is renamed from Avalon's FixedSizeBuffer. Made it extend AbstractCollection, provided an iterator. Removed "final" from class and method declarations. Added javadoc. UnboundedFifoBuffer is renamed from Avalon's VariableSizeBuffer. Made it extend AbstractCollection, provided an iterator. Removed "final" from class and method delcarations. Added javadoc. BufferUtils provides Buffer decorators for synchronized, unmodifiable, and predicated Buffers. git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@130740 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6f35a6f718
commit
9f3b7f5f43
|
@ -0,0 +1,287 @@
|
|||
/*
|
||||
* Copyright (C) The Apache Software Foundation. All rights reserved.
|
||||
*
|
||||
* This software is published under the terms of the Apache Software License
|
||||
* version 1.1, a copy of which has been included with this distribution in
|
||||
* the LICENSE.txt file.
|
||||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
|
||||
/**
|
||||
* The BoundedFifoBuffer is a <strong>very</strong> efficient implementation of
|
||||
* Buffer that does not alter the size of the buffer at runtime.<P>
|
||||
*
|
||||
* The removal order of a <Code>BoundedFifoBuffer</Code> is based on the
|
||||
* insertion order; elements are removed in the same order in which they
|
||||
* were added. The iteration order is the same as the removal order.<P>
|
||||
*
|
||||
* The {@link add(Object}, {@link remove()} and {@link get()} operations
|
||||
* all perform in constant time. All other operations perform in linear
|
||||
* time or worse.
|
||||
*
|
||||
* Note that this implementation is not synchronized. The following can be
|
||||
* used to provide synchronized access to your <COde>BoundedFifoBuffer</Code>:
|
||||
*
|
||||
* <Pre>
|
||||
* Buffer fifo = BufferUtils.synchronizedBuffer(new BoundedFifoBuffer());
|
||||
* </Pre>
|
||||
*
|
||||
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
|
||||
* @author Paul Jack
|
||||
* @version $Id: BoundedFifoBuffer.java,v 1.1 2002/07/03 01:57:08 mas Exp $
|
||||
*/
|
||||
public class BoundedFifoBuffer extends AbstractCollection implements Buffer
|
||||
{
|
||||
private final Object[] m_elements;
|
||||
private int m_start = 0;
|
||||
private int m_end = 0;
|
||||
private boolean m_full = false;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new <Code>BoundedFifoBuffer</Code> big enough to hold
|
||||
* the specified number of elements.
|
||||
*
|
||||
* @param size the maximum number of elements for this fifo
|
||||
*/
|
||||
public BoundedFifoBuffer( int size )
|
||||
{
|
||||
m_elements = new Object[ size ];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new <Code>BoundedFifoBuffer</Code> big enough to hold
|
||||
* 32 elements.
|
||||
*/
|
||||
public BoundedFifoBuffer()
|
||||
{
|
||||
this( 32 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new <Code>BoundedFifoBuffer</Code> big enough to hold all
|
||||
* of the elements in the specified collection. That collection's
|
||||
* elements will also be added to the fifo.
|
||||
*
|
||||
* @param c the collection whose elements to add
|
||||
*/
|
||||
public BoundedFifoBuffer(Collection c) {
|
||||
this(c.size());
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns this fifo's size.
|
||||
*
|
||||
* @return this fifo's size
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
if( m_end < m_start )
|
||||
{
|
||||
size = m_elements.length - m_start + m_end;
|
||||
}
|
||||
else if( m_end == m_start )
|
||||
{
|
||||
size = ( m_full ? m_elements.length : 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
size = m_end - m_start;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this fifo is empty; false otherwise.
|
||||
*
|
||||
* @return true if this fifo is empty
|
||||
*/
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the given element to this fifo.
|
||||
*
|
||||
* @param element the element to add
|
||||
* @return true, always
|
||||
* @throws NullPointerException if the given element is null
|
||||
* @throws BufferOverflowException if this fifo is full
|
||||
*/
|
||||
public boolean add( Object element )
|
||||
{
|
||||
if( null == element )
|
||||
{
|
||||
throw new NullPointerException( "Attempted to add null object to buffer" );
|
||||
}
|
||||
|
||||
if( m_full )
|
||||
{
|
||||
throw new BufferOverflowException( "The buffer cannot hold more than "
|
||||
+ m_elements.length + " objects." );
|
||||
}
|
||||
|
||||
m_elements[ m_end++ ] = element;
|
||||
|
||||
if( m_end >= m_elements.length )
|
||||
{
|
||||
m_end = 0;
|
||||
}
|
||||
|
||||
if( m_end == m_start )
|
||||
{
|
||||
m_full = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the least recently inserted element in this fifo.
|
||||
*
|
||||
* @return the least recently inserted element
|
||||
* @throws BufferUnderflowException if the fifo is empty
|
||||
*/
|
||||
public Object get() {
|
||||
if( isEmpty() )
|
||||
{
|
||||
throw new BufferUnderflowException( "The buffer is already empty" );
|
||||
}
|
||||
|
||||
return m_elements[ m_start ];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the least recently inserted element from this fifo.
|
||||
*
|
||||
* @return the least recently inserted element
|
||||
* @throws BufferUnderflowException if the fifo is empty
|
||||
*/
|
||||
public Object remove()
|
||||
{
|
||||
if( isEmpty() )
|
||||
{
|
||||
throw new BufferUnderflowException( "The buffer is already empty" );
|
||||
}
|
||||
|
||||
Object element = m_elements[ m_start ];
|
||||
|
||||
if( null != element )
|
||||
{
|
||||
m_elements[ m_start++ ] = null;
|
||||
|
||||
if( m_start >= m_elements.length )
|
||||
{
|
||||
m_start = 0;
|
||||
}
|
||||
|
||||
m_full = false;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
private int increment(int index) {
|
||||
index++;
|
||||
if (index >= m_elements.length) index = 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
private int decrement(int index) {
|
||||
index--;
|
||||
if (index < 0) index = m_elements.length - 1;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator over this fifo's elements.
|
||||
*
|
||||
* @return an iterator over this fifo's elements
|
||||
*/
|
||||
public Iterator iterator() {
|
||||
return new Iterator() {
|
||||
|
||||
private int index = m_start;
|
||||
private int lastReturnedIndex = -1;
|
||||
private boolean isFirst = m_full;
|
||||
|
||||
public boolean hasNext() {
|
||||
return isFirst || (index != m_end);
|
||||
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
isFirst = false;
|
||||
lastReturnedIndex = index;
|
||||
index = increment(index);
|
||||
return m_elements[lastReturnedIndex];
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (lastReturnedIndex == -1) throw new IllegalStateException();
|
||||
|
||||
// First element can be removed quickly
|
||||
if (lastReturnedIndex == m_start) {
|
||||
BoundedFifoBuffer.this.remove();
|
||||
lastReturnedIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Other elements require us to shift the subsequent elements
|
||||
int i = lastReturnedIndex + 1;
|
||||
while (i != m_end) {
|
||||
if (i >= m_elements.length) {
|
||||
m_elements[i - 1] = m_elements[0];
|
||||
i = 0;
|
||||
} else {
|
||||
m_elements[i - 1] = m_elements[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
lastReturnedIndex = -1;
|
||||
m_end = decrement(m_end);
|
||||
m_elements[m_end] = null;
|
||||
m_full = false;
|
||||
index = decrement(index);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears this fifo.
|
||||
*/
|
||||
public void clear() {
|
||||
m_full = false;
|
||||
m_start = 0;
|
||||
m_end = 0;
|
||||
Arrays.fill(m_elements, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,340 @@
|
|||
package org.apache.commons.collections;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Contains static utility methods for operating on {@link Buffer} objects.
|
||||
*
|
||||
* @author Paul Jack
|
||||
* @version $Id: BufferUtils.java,v 1.1 2002/07/03 01:57:08 mas Exp $
|
||||
*/
|
||||
public class BufferUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Returns a synchronized buffer backed by the given buffer.
|
||||
* Much like the synchronized collections returned by
|
||||
* {@link java.util.Collections}, you must manually synchronize on
|
||||
* the returned buffer's iterator to avoid non-deterministic behavior:
|
||||
*
|
||||
* <Pre>
|
||||
* Buffer b = BufferUtils.synchronizedBuffer(myBuffer);
|
||||
* synchronized (b) {
|
||||
* Iterator i = b.iterator();
|
||||
* while (i.hasNext()) {
|
||||
* process (i.next());
|
||||
* }
|
||||
* }
|
||||
* </Pre>
|
||||
*
|
||||
* @param b the buffer to synchronize
|
||||
* @return a synchronized buffer backed by that buffer
|
||||
*/
|
||||
public static Buffer synchronizedBuffer(final Buffer b) {
|
||||
return new SynchronizedBuffer(b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a synchronized buffer backed by the given buffer that will
|
||||
* block on {@link Buffer.get()} and {@link Buffer.remove()} operations.
|
||||
* If the buffer is empty, then the {@link Buffer.get()} and
|
||||
* {@link Buffer.remove()} operations will block until new elements
|
||||
* are added to the buffer, rather than immediately throwing a
|
||||
* <Code>BufferUnderflowException</Code>.
|
||||
*
|
||||
* @param buf the buffer to synchronize
|
||||
* @return a blocking buffer backed by that buffer
|
||||
*/
|
||||
public static Buffer blockingBuffer(Buffer buf) {
|
||||
return new SynchronizedBuffer(buf) {
|
||||
|
||||
public synchronized boolean add(Object o) {
|
||||
boolean r = b.add(o);
|
||||
notify();
|
||||
return r;
|
||||
}
|
||||
|
||||
public synchronized boolean addAll(Collection c) {
|
||||
boolean r = b.addAll(c);
|
||||
notifyAll();
|
||||
return r;
|
||||
}
|
||||
|
||||
public synchronized Object get() {
|
||||
while (b.isEmpty()) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new BufferUnderflowException();
|
||||
}
|
||||
}
|
||||
return b.get();
|
||||
}
|
||||
|
||||
public synchronized Object remove() {
|
||||
while (b.isEmpty()) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new BufferUnderflowException();
|
||||
}
|
||||
}
|
||||
return b.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static class SynchronizedBuffer implements Buffer {
|
||||
|
||||
Buffer b;
|
||||
|
||||
|
||||
public SynchronizedBuffer(Buffer b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public synchronized int size() {
|
||||
return b.size();
|
||||
}
|
||||
|
||||
public synchronized boolean isEmpty() {
|
||||
return b.isEmpty();
|
||||
}
|
||||
|
||||
public synchronized boolean contains(Object o) {
|
||||
return b.contains(o);
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
return b.iterator();
|
||||
}
|
||||
|
||||
public synchronized Object[] toArray() {
|
||||
return b.toArray();
|
||||
}
|
||||
|
||||
public synchronized Object[] toArray(Object[] o) {
|
||||
return b.toArray(o);
|
||||
}
|
||||
|
||||
public synchronized boolean add(Object o) {
|
||||
return b.add(o);
|
||||
}
|
||||
|
||||
public synchronized boolean remove(Object o) {
|
||||
return b.remove(o);
|
||||
}
|
||||
|
||||
public synchronized boolean containsAll(Collection c) {
|
||||
return b.containsAll(c);
|
||||
}
|
||||
|
||||
public synchronized boolean addAll(Collection c) {
|
||||
return b.addAll(c);
|
||||
}
|
||||
|
||||
public synchronized boolean removeAll(Collection c) {
|
||||
return b.removeAll(c);
|
||||
}
|
||||
|
||||
public synchronized boolean retainAll(Collection c) {
|
||||
return b.retainAll(c);
|
||||
}
|
||||
|
||||
public synchronized void clear() {
|
||||
b.clear();
|
||||
}
|
||||
|
||||
public synchronized boolean equals(Object o) {
|
||||
return b.equals(o);
|
||||
}
|
||||
|
||||
public synchronized int hashCode() {
|
||||
return b.hashCode();
|
||||
}
|
||||
|
||||
public synchronized String toString() {
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public synchronized Object get() {
|
||||
return b.get();
|
||||
}
|
||||
|
||||
public synchronized Object remove() {
|
||||
return b.remove();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable buffer backed by the given buffer.
|
||||
*
|
||||
* @param b the buffer to make unmodifiable
|
||||
* @return an unmodifiable buffer backed by that buffer
|
||||
*/
|
||||
public static Buffer unmodifiableBuffer(Buffer b) {
|
||||
return new BufferDecorator(b) {
|
||||
public boolean addAll(Collection c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean add(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a predicated buffer backed by the given buffer. Elements are
|
||||
* evaluated with the given predicate before being added to the buffer.
|
||||
* If the predicate evaluation returns false, then an
|
||||
* IllegalArgumentException is raised and the element is not added to
|
||||
* the buffer.
|
||||
*
|
||||
* @param buf the buffer to predicate
|
||||
* @param p the predicate used to evaluate new elements
|
||||
* @return a predicated buffer
|
||||
*/
|
||||
public static Buffer predicatedBuffer(Buffer buf, final Predicate p) {
|
||||
if (buf == null) {
|
||||
throw new IllegalArgumentException("Buffer must not be null.");
|
||||
}
|
||||
if (p == null) {
|
||||
throw new IllegalArgumentException("Predicate must not be null.");
|
||||
}
|
||||
return new BufferDecorator(buf) {
|
||||
|
||||
public boolean add(Object o) {
|
||||
test(o);
|
||||
return b.add(o);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection c) {
|
||||
Iterator iterator = c.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
test(iterator.next());
|
||||
}
|
||||
return b.addAll(c);
|
||||
}
|
||||
|
||||
private void test(Object o) {
|
||||
if (!p.evaluate(o)) {
|
||||
throw new IllegalArgumentException("Invalid: " + o);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static class BufferDecorator implements Buffer {
|
||||
|
||||
Buffer b;
|
||||
|
||||
BufferDecorator(Buffer b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return b.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return b.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return b.contains(o);
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
return b.iterator();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return b.toArray();
|
||||
}
|
||||
|
||||
public Object[] toArray(Object[] o) {
|
||||
return b.toArray(o);
|
||||
}
|
||||
|
||||
public boolean add(Object o) {
|
||||
return b.add(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return b.remove(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection c) {
|
||||
return b.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection c) {
|
||||
return b.addAll(c);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection c) {
|
||||
return b.removeAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection c) {
|
||||
return b.retainAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
b.clear();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return b.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return b.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public Object get() {
|
||||
return b.get();
|
||||
}
|
||||
|
||||
public Object remove() {
|
||||
return b.remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* Copyright (C) The Apache Software Foundation. All rights reserved.
|
||||
*
|
||||
* This software is published under the terms of the Apache Software License
|
||||
* version 1.1, a copy of which has been included with this distribution in
|
||||
* the LICENSE.txt file.
|
||||
*/
|
||||
package org.apache.commons.collections;
|
||||
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
|
||||
/**
|
||||
* UnboundedFifoBuffer is a <strong>very</strong> efficient buffer implementation.
|
||||
* According to performance testing, it exhibits a constant access time, but it
|
||||
* also outperforms ArrayList when used for the same purpose.
|
||||
* <P>
|
||||
* The removal order of an <Code>UnboundedFifoBuffer</Code> is based on the insertion
|
||||
* order; elements are removed in the same order in which they were added.
|
||||
* The iteration order is the same as the removal order.<P>
|
||||
*
|
||||
* The {@link remove()} and {@link get()} operations perform in constant time.
|
||||
* The {@link add()} operation performs in amortized constant time. All
|
||||
* other operations perform in linear time or worse.<P>
|
||||
*
|
||||
* Note that this implementation is not synchronized. The following can be
|
||||
* used to provide synchronized access to your <COde>BoundedFifo</Code>:
|
||||
*
|
||||
* <Pre>
|
||||
* Buffer fifo = BufferUtils.synchronizedBuffer(new BoundedFifo());
|
||||
* </Pre>
|
||||
*
|
||||
* @author <a href="fede@apache.org">Federico Barbieri</a>
|
||||
* @author <a href="bloritsch@apache.org">Berin Loritsch</a>
|
||||
* @author Paul Jack
|
||||
* @version CVS $Revision: 1.1 $ $Date: 2002/07/03 01:57:08 $
|
||||
* @since Avalon 4.0
|
||||
*/
|
||||
public final class UnboundedFifoBuffer extends AbstractCollection implements Buffer
|
||||
{
|
||||
protected Object[] m_buffer;
|
||||
protected int m_head;
|
||||
protected int m_tail;
|
||||
|
||||
/**
|
||||
* Initialize the UnboundedFifoBuffer with the specified number of elements. The
|
||||
* integer must be a positive integer.
|
||||
*/
|
||||
public UnboundedFifoBuffer( int size )
|
||||
{
|
||||
m_buffer = new Object[ size + 1 ];
|
||||
m_head = 0;
|
||||
m_tail = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the UnboundedFifoBuffer with the default number of elements. It is
|
||||
* exactly the same as performing the following:
|
||||
*
|
||||
* <pre>
|
||||
* new UnboundedFifoBuffer( 32 );
|
||||
* </pre>
|
||||
*/
|
||||
public UnboundedFifoBuffer()
|
||||
{
|
||||
this( 32 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if the CircularBuffer is empty.
|
||||
*/
|
||||
public final boolean isEmpty()
|
||||
{
|
||||
return ( size() == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements stored in the buffer.
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
if( m_tail < m_head )
|
||||
{
|
||||
size = m_buffer.length - m_head + m_tail;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = m_tail - m_head;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an object into the buffer
|
||||
*/
|
||||
public boolean add( final Object o )
|
||||
{
|
||||
if( null == o )
|
||||
{
|
||||
throw new NullPointerException( "Attempted to add null object to buffer" );
|
||||
}
|
||||
|
||||
if( size() + 1 >= m_buffer.length )
|
||||
{
|
||||
Object[] tmp = new Object[ ( ( m_buffer.length - 1 ) * 2 ) + 1 ];
|
||||
|
||||
int j = 0;
|
||||
for( int i = m_head; i != m_tail; )
|
||||
{
|
||||
tmp[ j ] = m_buffer[ i ];
|
||||
m_buffer[ i ] = null;
|
||||
|
||||
j++;
|
||||
i++;
|
||||
if( i == m_buffer.length )
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_buffer = tmp;
|
||||
m_head = 0;
|
||||
m_tail = j;
|
||||
}
|
||||
|
||||
m_buffer[ m_tail ] = o;
|
||||
m_tail++;
|
||||
if( m_tail >= m_buffer.length )
|
||||
{
|
||||
m_tail = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next object in the buffer.
|
||||
*
|
||||
* @return the next object in the buffer
|
||||
* @throws BufferUnderflowException if this buffer is empty
|
||||
*/
|
||||
public Object get()
|
||||
{
|
||||
if( isEmpty() )
|
||||
{
|
||||
throw new BufferUnderflowException( "The buffer is already empty" );
|
||||
}
|
||||
|
||||
return m_buffer[ m_head ];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the next object from the buffer
|
||||
*
|
||||
* @return the removed object
|
||||
* @throws BufferUnderflowException if this buffer is empty
|
||||
*/
|
||||
public Object remove()
|
||||
{
|
||||
if( isEmpty() )
|
||||
{
|
||||
throw new BufferUnderflowException( "The buffer is already empty" );
|
||||
}
|
||||
|
||||
Object element = m_buffer[ m_head ];
|
||||
|
||||
if( null != element )
|
||||
{
|
||||
m_buffer[ m_head ] = null;
|
||||
|
||||
m_head++;
|
||||
if( m_head >= m_buffer.length )
|
||||
{
|
||||
m_head = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
private int increment(int index) {
|
||||
index++;
|
||||
if (index >= m_buffer.length) index = 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
private int decrement(int index) {
|
||||
index--;
|
||||
if (index < 0) index = m_buffer.length - 1;
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator over this fifo's elements.
|
||||
*
|
||||
* @return an iterator over this fifo's elements
|
||||
*/
|
||||
public Iterator iterator() {
|
||||
return new Iterator() {
|
||||
|
||||
private int index = m_head;
|
||||
private int lastReturnedIndex = -1;
|
||||
|
||||
public boolean hasNext() {
|
||||
return index != m_tail;
|
||||
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
lastReturnedIndex = index;
|
||||
index = increment(index);
|
||||
return m_buffer[lastReturnedIndex];
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if (lastReturnedIndex == -1) throw new IllegalStateException();
|
||||
|
||||
// First element can be removed quickly
|
||||
if (lastReturnedIndex == m_head) {
|
||||
UnboundedFifoBuffer.this.remove();
|
||||
lastReturnedIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Other elements require us to shift the subsequent elements
|
||||
int i = lastReturnedIndex + 1;
|
||||
while (i != m_tail) {
|
||||
if (i >= m_buffer.length) {
|
||||
m_buffer[i - 1] = m_buffer[0];
|
||||
i = 0;
|
||||
} else {
|
||||
m_buffer[i - 1] = m_buffer[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
lastReturnedIndex = -1;
|
||||
m_tail = decrement(m_tail);
|
||||
m_buffer[m_tail] = null;
|
||||
index = decrement(index);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestAll.java,v 1.28 2002/06/21 06:17:45 mas Exp $
|
||||
* $Revision: 1.28 $
|
||||
* $Date: 2002/06/21 06:17:45 $
|
||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestAll.java,v 1.29 2002/07/03 01:57:08 mas Exp $
|
||||
* $Revision: 1.29 $
|
||||
* $Date: 2002/07/03 01:57:08 $
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
|
@ -67,7 +67,7 @@ import junit.framework.*;
|
|||
/**
|
||||
* Entry point for all Collections tests.
|
||||
* @author Rodney Waldhoff
|
||||
* @version $Id: TestAll.java,v 1.28 2002/06/21 06:17:45 mas Exp $
|
||||
* @version $Id: TestAll.java,v 1.29 2002/07/03 01:57:08 mas Exp $
|
||||
*/
|
||||
public class TestAll extends TestCase {
|
||||
public TestAll(String testName) {
|
||||
|
@ -81,6 +81,8 @@ public class TestAll extends TestCase {
|
|||
suite.addTest(TestArrayStack.suite());
|
||||
suite.addTest(TestBeanMap.suite());
|
||||
suite.addTest(TestBinaryHeap.suite());
|
||||
suite.addTest(TestBoundedFifoBuffer.suite());
|
||||
suite.addTest(TestBoundedFifoBuffer2.suite());
|
||||
suite.addTest(TestCollectionUtils.suite());
|
||||
suite.addTest(TestComparableComparator.suite());
|
||||
suite.addTest(TestComparatorChain.suite());
|
||||
|
@ -106,6 +108,7 @@ public class TestAll extends TestCase {
|
|||
suite.addTest(TestSingletonIterator.suite());
|
||||
suite.addTest(TestStaticBucketMap.suite());
|
||||
suite.addTest(TestTreeBag.suite());
|
||||
suite.addTest(TestUnboundedFifoBuffer.suite());
|
||||
suite.addTest(TestUniqueFilterIterator.suite());
|
||||
suite.addTest(org.apache.commons.collections.primitives.TestAll.suite());
|
||||
return suite;
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package org.apache.commons.collections;
|
||||
|
||||
|
||||
import junit.framework.Test;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Test cases for BoundedFifoBuffer.
|
||||
*/
|
||||
public class TestBoundedFifoBuffer extends TestCollection {
|
||||
|
||||
public TestBoundedFifoBuffer(String n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return BulkTest.makeSuite(TestBoundedFifoBuffer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty BoundedFifoBuffer that won't overflow.
|
||||
*
|
||||
* @return an empty BoundedFifoBuffer
|
||||
*/
|
||||
public Collection makeCollection() {
|
||||
return new BoundedFifoBuffer(100);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns an empty ArrayList.
|
||||
*
|
||||
* @return an empty ArrayList
|
||||
*/
|
||||
public Collection makeConfirmedCollection() {
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a full ArrayList.
|
||||
*
|
||||
* @return a full ArrayList
|
||||
*/
|
||||
public Collection makeConfirmedFullCollection() {
|
||||
Collection c = makeConfirmedCollection();
|
||||
c.addAll(java.util.Arrays.asList(getFullElements()));
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden because BoundedFifoBuffer doesn't support null elements.
|
||||
*
|
||||
* @return an array of random objects without a null element
|
||||
*/
|
||||
public Object[] getFullElements() {
|
||||
return getFullNonNullElements();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden, because BoundedFifoBuffer's iterators aren't fail-fast.
|
||||
*/
|
||||
public void testCollectionIteratorFailFast() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs through the regular verifications, but also verifies that
|
||||
* the buffer contains the same elements in the same sequence as the
|
||||
* list.
|
||||
*/
|
||||
public void verify() {
|
||||
super.verify();
|
||||
Iterator iterator1 = collection.iterator();
|
||||
Iterator iterator2 = confirmed.iterator();
|
||||
while (iterator2.hasNext()) {
|
||||
assertTrue(iterator1.hasNext());
|
||||
Object o1 = iterator1.next();
|
||||
Object o2 = iterator2.next();
|
||||
assertEquals(o1, o2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the removal operation actually removes the first element.
|
||||
*/
|
||||
public void testBoundedFifoBufferRemove() {
|
||||
resetFull();
|
||||
int size = confirmed.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Object o1 = ((BoundedFifoBuffer)collection).remove();
|
||||
Object o2 = ((ArrayList)confirmed).remove(0);
|
||||
assertEquals("Removed objects should be equal", o1, o2);
|
||||
verify();
|
||||
}
|
||||
|
||||
try {
|
||||
((BoundedFifoBuffer)collection).remove();
|
||||
fail("Empty buffer should raise Underflow.");
|
||||
} catch (BufferUnderflowException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package org.apache.commons.collections;
|
||||
|
||||
|
||||
import junit.framework.Test;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Runs tests against a full BoundedFifoBuffer, since many of the algorithms
|
||||
* differ depending on whether the fifo is full or not.
|
||||
*/
|
||||
public class TestBoundedFifoBuffer2 extends TestBoundedFifoBuffer {
|
||||
|
||||
public TestBoundedFifoBuffer2(String n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return BulkTest.makeSuite(TestBoundedFifoBuffer2.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BoundedFifoBuffer that's filled to capacity.
|
||||
* Any attempt to add to the returned buffer will result in a
|
||||
* BufferOverflowException.
|
||||
*
|
||||
* @return a full BoundedFifoBuffer
|
||||
*/
|
||||
public Collection makeFullCollection() {
|
||||
return new BoundedFifoBuffer(Arrays.asList(getFullElements()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden to skip the add tests. All of them would fail with a
|
||||
* BufferOverflowException.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
public boolean isAddSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden because the add operations raise BufferOverflowException
|
||||
* instead of UnsupportedOperationException.
|
||||
*/
|
||||
public void testUnsupportedAdd() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests to make sure the add operations raise BufferOverflowException.
|
||||
*/
|
||||
public void testBufferOverflow() {
|
||||
resetFull();
|
||||
try {
|
||||
collection.add(getOtherElements()[0]);
|
||||
fail("add should raise BufferOverflow.");
|
||||
} catch (BufferOverflowException e) {
|
||||
// expected
|
||||
}
|
||||
verify();
|
||||
|
||||
try {
|
||||
collection.addAll(Arrays.asList(getOtherElements()));
|
||||
fail("addAll should raise BufferOverflow.");
|
||||
} catch (BufferOverflowException e) {
|
||||
// expected
|
||||
}
|
||||
verify();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package org.apache.commons.collections;
|
||||
|
||||
|
||||
import junit.framework.Test;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Test cases for UnboundedFifoBuffer.
|
||||
*/
|
||||
public class TestUnboundedFifoBuffer extends TestCollection {
|
||||
|
||||
public TestUnboundedFifoBuffer(String n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return BulkTest.makeSuite(TestUnboundedFifoBuffer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty UnboundedFifoBuffer with a small capacity.
|
||||
*
|
||||
* @return an empty UnboundedFifoBuffer
|
||||
*/
|
||||
public Collection makeCollection() {
|
||||
return new UnboundedFifoBuffer(5);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an empty ArrayList.
|
||||
*
|
||||
* @return an empty ArrayList
|
||||
*/
|
||||
public Collection makeConfirmedCollection() {
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a full ArrayList.
|
||||
*
|
||||
* @return a full ArrayList
|
||||
*/
|
||||
public Collection makeConfirmedFullCollection() {
|
||||
Collection c = makeConfirmedCollection();
|
||||
c.addAll(java.util.Arrays.asList(getFullElements()));
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden because UnboundedFifoBuffer doesn't allow null elements.
|
||||
*
|
||||
* @return an array of random elements without the null element
|
||||
*/
|
||||
public Object[] getFullElements() {
|
||||
return getFullNonNullElements();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden because UnboundedFifoBuffer's iterators aren't fail-fast.
|
||||
*/
|
||||
public void testCollectionIteratorFailFast() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the ArrayList has the same elements in the same
|
||||
* sequence as the UnboundedFifoBuffer.
|
||||
*/
|
||||
public void verify() {
|
||||
super.verify();
|
||||
Iterator iterator1 = collection.iterator();
|
||||
Iterator iterator2 = confirmed.iterator();
|
||||
while (iterator2.hasNext()) {
|
||||
assertTrue(iterator1.hasNext());
|
||||
Object o1 = iterator1.next();
|
||||
Object o2 = iterator2.next();
|
||||
assertEquals(o1, o2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests that UnboundedFifoBuffer removes elements in the right order.
|
||||
*/
|
||||
public void testUnboundedFifoBufferRemove() {
|
||||
resetFull();
|
||||
int size = confirmed.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Object o1 = ((UnboundedFifoBuffer)collection).remove();
|
||||
Object o2 = ((ArrayList)confirmed).remove(0);
|
||||
assertEquals("Removed objects should be equal", o1, o2);
|
||||
verify();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue