SuballocatedByteVectorpublic class SuballocatedByteVector extends Object A very simple table that stores a list of byte. Very similar API to our
IntVector class (same API); different internal storage.
This version uses an array-of-arrays solution. Read/write access is thus
a bit slower than the simple IntVector, and basic storage is a trifle
higher due to the top-level array -- but appending is O(1) fast rather
than O(N**2) slow, which will swamp those costs in situations where
long vectors are being built up.
Known issues:
Some methods are private because they haven't yet been tested properly.
If an element has not been set (because we skipped it), its value will
initially be 0. Shortening the vector does not clear old storage; if you
then skip values and setElementAt a higher index again, you may see old data
reappear in the truncated-and-restored section. Doing anything else would
have performance costs. |
Fields Summary |
---|
protected int | m_blocksizeSize of blocks to allocate | protected int | m_numblocksNumber of blocks to (over)allocate by | protected byte[] | m_mapArray of arrays of bytes | protected int | m_firstFreeNumber of bytes in array | protected byte[] | m_map0"Shortcut" handle to m_map[0] |
Constructors Summary |
---|
public SuballocatedByteVector()Default constructor. Note that the default
block size is very small, for small lists.
this(2048);
| public SuballocatedByteVector(int blocksize)Construct a ByteVector, using the given block size.
m_blocksize = blocksize;
m_map0=new byte[blocksize];
m_map = new byte[m_numblocks][];
m_map[0]=m_map0;
| public SuballocatedByteVector(int blocksize, int increaseSize)Construct a ByteVector, using the given block size.
// increaseSize not currently used.
this(blocksize);
|
Methods Summary |
---|
public void | addElement(byte value)Append a byte onto the vector.
if(m_firstFree<m_blocksize)
m_map0[m_firstFree++]=value;
else
{
int index=m_firstFree/m_blocksize;
int offset=m_firstFree%m_blocksize;
++m_firstFree;
if(index>=m_map.length)
{
int newsize=index+m_numblocks;
byte[][] newMap=new byte[newsize][];
System.arraycopy(m_map, 0, newMap, 0, m_map.length);
m_map=newMap;
}
byte[] block=m_map[index];
if(null==block)
block=m_map[index]=new byte[m_blocksize];
block[offset]=value;
}
| private void | addElements(byte value, int numberOfElements)Append several byte values onto the vector.
if(m_firstFree+numberOfElements<m_blocksize)
for (int i = 0; i < numberOfElements; i++)
{
m_map0[m_firstFree++]=value;
}
else
{
int index=m_firstFree/m_blocksize;
int offset=m_firstFree%m_blocksize;
m_firstFree+=numberOfElements;
while( numberOfElements>0)
{
if(index>=m_map.length)
{
int newsize=index+m_numblocks;
byte[][] newMap=new byte[newsize][];
System.arraycopy(m_map, 0, newMap, 0, m_map.length);
m_map=newMap;
}
byte[] block=m_map[index];
if(null==block)
block=m_map[index]=new byte[m_blocksize];
int copied=(m_blocksize-offset < numberOfElements)
? m_blocksize-offset : numberOfElements;
numberOfElements-=copied;
while(copied-- > 0)
block[offset++]=value;
++index;offset=0;
}
}
| private void | addElements(int numberOfElements)Append several slots onto the vector, but do not set the values.
Note: "Not Set" means the value is unspecified.
int newlen=m_firstFree+numberOfElements;
if(newlen>m_blocksize)
{
int index=m_firstFree%m_blocksize;
int newindex=(m_firstFree+numberOfElements)%m_blocksize;
for(int i=index+1;i<=newindex;++i)
m_map[i]=new byte[m_blocksize];
}
m_firstFree=newlen;
| private boolean | contains(byte s)Tell if the table contains the given node.
return (indexOf(s,0) >= 0);
| public byte | elementAt(int i)Get the nth element. This is often at the innermost loop of an
application, so performance is critical.
// %OPT% Does this really buy us anything? Test versus division for small,
// test _plus_ division for big docs.
if(i<m_blocksize)
return m_map0[i];
return m_map[i/m_blocksize][i%m_blocksize];
| public int | indexOf(byte elem, int index)Searches for the first occurence of the given argument,
beginning the search at index, and testing for equality
using the equals method.
if(index>=m_firstFree)
return -1;
int bindex=index/m_blocksize;
int boffset=index%m_blocksize;
int maxindex=m_firstFree/m_blocksize;
byte[] block;
for(;bindex<maxindex;++bindex)
{
block=m_map[bindex];
if(block!=null)
for(int offset=boffset;offset<m_blocksize;++offset)
if(block[offset]==elem)
return offset+bindex*m_blocksize;
boffset=0; // after first
}
// Last block may need to stop before end
int maxoffset=m_firstFree%m_blocksize;
block=m_map[maxindex];
for(int offset=boffset;offset<maxoffset;++offset)
if(block[offset]==elem)
return offset+maxindex*m_blocksize;
return -1;
| public int | indexOf(byte elem)Searches for the first occurence of the given argument,
beginning the search at index, and testing for equality
using the equals method.
return indexOf(elem,0);
| private void | insertElementAt(byte value, int at)Inserts the specified node in this vector at the specified index.
Each component in this vector with an index greater or equal to
the specified index is shifted upward to have an index one greater
than the value it had previously.
Insertion may be an EXPENSIVE operation!
if(at==m_firstFree)
addElement(value);
else if (at>m_firstFree)
{
int index=at/m_blocksize;
if(index>=m_map.length)
{
int newsize=index+m_numblocks;
byte[][] newMap=new byte[newsize][];
System.arraycopy(m_map, 0, newMap, 0, m_map.length);
m_map=newMap;
}
byte[] block=m_map[index];
if(null==block)
block=m_map[index]=new byte[m_blocksize];
int offset=at%m_blocksize;
block[offset]=value;
m_firstFree=offset+1;
}
else
{
int index=at/m_blocksize;
int maxindex=m_firstFree+1/m_blocksize;
++m_firstFree;
int offset=at%m_blocksize;
byte push;
// ***** Easier to work down from top?
while(index<=maxindex)
{
int copylen=m_blocksize-offset-1;
byte[] block=m_map[index];
if(null==block)
{
push=0;
block=m_map[index]=new byte[m_blocksize];
}
else
{
push=block[m_blocksize-1];
System.arraycopy(block, offset , block, offset+1, copylen);
}
block[offset]=value;
value=push;
offset=0;
++index;
}
}
| private int | lastIndexOf(byte elem)Searches for the first occurence of the given argument,
beginning the search at index, and testing for equality
using the equals method.
int boffset=m_firstFree%m_blocksize;
for(int index=m_firstFree/m_blocksize;
index>=0;
--index)
{
byte[] block=m_map[index];
if(block!=null)
for(int offset=boffset; offset>=0; --offset)
if(block[offset]==elem)
return offset+index*m_blocksize;
boffset=0; // after first
}
return -1;
| public void | removeAllElements()Wipe it out.
m_firstFree = 0;
| private boolean | removeElement(byte s)Removes the first occurrence of the argument from this vector.
If the object is found in this vector, each component in the vector
with an index greater or equal to the object's index is shifted
downward to have an index one smaller than the value it had
previously.
int at=indexOf(s,0);
if(at<0)
return false;
removeElementAt(at);
return true;
| private void | removeElementAt(int at)Deletes the component at the specified index. Each component in
this vector with an index greater or equal to the specified
index is shifted downward to have an index one smaller than
the value it had previously.
// No point in removing elements that "don't exist"...
if(at<m_firstFree)
{
int index=at/m_blocksize;
int maxindex=m_firstFree/m_blocksize;
int offset=at%m_blocksize;
while(index<=maxindex)
{
int copylen=m_blocksize-offset-1;
byte[] block=m_map[index];
if(null==block)
block=m_map[index]=new byte[m_blocksize];
else
System.arraycopy(block, offset+1, block, offset, copylen);
if(index<maxindex)
{
byte[] next=m_map[index+1];
if(next!=null)
block[m_blocksize-1]=(next!=null) ? next[0] : 0;
}
else
block[m_blocksize-1]=0;
offset=0;
++index;
}
}
--m_firstFree;
| public void | setElementAt(byte value, int at)Sets the component at the specified index of this vector to be the
specified object. The previous component at that position is discarded.
The index must be a value greater than or equal to 0 and less
than the current size of the vector.
if(at<m_blocksize)
{
m_map0[at]=value;
return;
}
int index=at/m_blocksize;
int offset=at%m_blocksize;
if(index>=m_map.length)
{
int newsize=index+m_numblocks;
byte[][] newMap=new byte[newsize][];
System.arraycopy(m_map, 0, newMap, 0, m_map.length);
m_map=newMap;
}
byte[] block=m_map[index];
if(null==block)
block=m_map[index]=new byte[m_blocksize];
block[offset]=value;
if(at>=m_firstFree)
m_firstFree=at+1;
| private void | setSize(int sz)Set the length of the list.
if(m_firstFree<sz)
m_firstFree = sz;
| public int | size()Get the length of the list.
return m_firstFree;
|
|