FloatAppendList.java
package nl.tudelft.simulation.dsol.animation.graph;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* FloatList is a random access list of float values to which values can only be appended. It stores the values as primitives
* rather than as wrapping Objects. For the rest, it behaves like a regular list, with the exception of the absence of the
* add(i, value) method and the remove methods.
* <p>
* Copyright (c) 2020-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The DSOL
* project is distributed under a three-clause BSD-style license, which can be found at
* <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
* </p>
* @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
*/
public class FloatAppendList implements Iterable<Float>, Serializable
{
/** */
private static final long serialVersionUID = 20210103L;
/** the chunk size. */
private static final int CHUNK_SIZE = 256;
/** the number of bits of the chunk size. */
private static final int CHUNK_BITS = 8;
/** the mask for the rightmost CHUNK_BITS bits. */
private static final int CHUNK_MASK = CHUNK_SIZE - 1;
/** the backing list with chunks. */
private final List<float[]> storage = new ArrayList<>();
/** the current chunk, already stored in the List. */
private float[] currentChunk;
/** the total number of elements. */
private int numElements;
/** the current in-chunk counter that indicates the next value to be written. */
private int inChunkNext;
/**
* Initialize the FloatAppendList.
*/
public FloatAppendList()
{
this.numElements = 0;
this.inChunkNext = 0;
this.currentChunk = new float[CHUNK_SIZE];
this.storage.add(this.currentChunk);
}
/**
* Add a value to the list.
* @param value float; the value to add
*/
public void add(final float value)
{
if (this.inChunkNext == CHUNK_SIZE)
{
this.inChunkNext = 0;
this.currentChunk = new float[CHUNK_SIZE];
this.storage.add(this.currentChunk);
}
this.currentChunk[this.inChunkNext] = value;
this.inChunkNext++;
this.numElements++;
}
/**
* Return the number of elements.
* @return int; the number of elements
*/
public int size()
{
return this.numElements;
}
/**
* Return the value at a position.
* @param i int; the position
* @return float; the value at the position
* @throws IndexOutOfBoundsException when i < 0 or i > number of values
*/
public float get(final int i)
{
if (i < 0 || i >= this.numElements)
{
throw new IndexOutOfBoundsException("FloatAppendList.get(i) -- i out of bounds.");
}
return this.storage.get(i >> CHUNK_BITS)[i & CHUNK_MASK];
}
/** {@inheritDoc} */
@Override
public Iterator<Float> iterator()
{
return new FloatAppendIterator(this);
}
/**
* An iterator for the FloatAppendList.
*/
class FloatAppendIterator implements Iterator<Float>
{
/** the list to iterate over. */
private final FloatAppendList list;
/** the counter. */
private int counter;
/**
* Make an iterator for the FloatAppendList.
* @param list FloatAppendList; the list to iterate over
*/
FloatAppendIterator(final FloatAppendList list)
{
this.list = list;
this.counter = 0;
}
/** {@inheritDoc} */
@Override
public boolean hasNext()
{
return this.counter < this.list.size();
}
/** {@inheritDoc} */
@Override
public Float next()
{
return this.list.get(this.counter++);
}
}
}