blob: 59a3f1d388d96170c3a20498e194a8539a56b3cc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.uima.internal.util;
import java.io.Serializable;
/**
* Like {@link java.util.Vector java.util.Vector}, but elements are <code>int</code>s. This is a
* bare-bones implementation. May add features as I need them.
*
*
*
*/
public class IntVector implements Serializable {
private static final long serialVersionUID = 4829243434421992519L;
private static final int default_size = 16;
private static final int default_growth_factor = 2;
private static final int default_multiplication_limit = 2000000;
private int growth_factor;
private int multiplication_limit;
// Points to the next free cell in the array.
protected int pos = 0;
protected int[] array = null;
/**
* Default constructor.
*/
public IntVector() {
this(default_size, default_growth_factor, default_multiplication_limit);
}
/**
* Construct an IntVector from an array. The array is not copied and may subsequently be modified.
*
* @param array
* The array the IntVector is initialized from.
*/
public IntVector(int[] array) {
if (array == null) {
array = new int[0];
}
this.pos = array.length;
this.array = array;
this.growth_factor = default_growth_factor;
this.multiplication_limit = default_multiplication_limit;
}
/**
* Specify the initial capacity of this vector. Use to avoid internal copying if you know ahead of
* time how large your vector is going to get (at least).
*
* @param capacity
* Initial capacity of vector.
*/
public IntVector(int capacity) {
this(capacity, default_growth_factor, default_multiplication_limit);
}
/**
* Specify the initial capacity, growth factor and multiplication limit of this vector. Use to
* avoid internal copying if you know ahead of time how large your vector is going to get (at
* least).
*
* @param capacity
* Initial capacity of vector.
* @param growth_factor
* Growth factor.
* @param multiplication_limit
* Multiplication limit.
*/
public IntVector(int capacity, int growth_factor, int multiplication_limit) {
if (capacity < 0) {
capacity = default_size;
}
if (growth_factor < 1) {
growth_factor = default_growth_factor;
}
if (multiplication_limit < 1) {
multiplication_limit = default_multiplication_limit;
}
this.growth_factor = growth_factor;
this.multiplication_limit = multiplication_limit;
this.array = new int[capacity];
}
public void setSize(int size) {
if (size > 0) {
this.ensure_size(size);
}
}
/**
* Add an element at the end of vector. Behaves like add(Object o) of
* {@link java.util.Vector Vector}.
*/
public void add(int element) {
final int i = this.pos;
++this.pos;
ensure_size(this.pos);
this.array[i] = element;
}
/**
* Add an element at a certain position in the vector. Elements later in the vector are shifted
* right by one. If the position is past the end of the current vector, new <code>0</code>-valued
* elements are added.
*/
public void add(int index, int element) {
if (index >= this.pos) {
ensure_size(index + 1);
} else {
if (this.array.length <= this.pos) {
ensure_size(this.pos + 1);
} else {
++this.pos;
}
System.arraycopy(this.array, index, this.array, index + 1, this.pos - (index + 1));
}
this.array[index] = element;
}
/**
* Set an element at a certain position in the vector.
*/
public void set(int index, int element) {
if (index >= this.pos) {
throw new ArrayIndexOutOfBoundsException();
}
this.array[index] = element;
}
/**
* Set an element at a certain position in the vector. Vector will grow.
*/
public void put(int index, int element) {
ensure_size(index + 1);
this.array[index] = element;
}
/**
* Retrieve the element at index.
*
* @return The element at <code>index</code>.
* @exception ArrayIndexOutOfBoundsException
* If <code>index</code> is not a valid index.
*/
public int get(int index) {
// Will throw an ArrayIndexOutOfBoundsException if out of bounds.
if (index >= this.pos) {
throw new ArrayIndexOutOfBoundsException();
}
return this.array[index];
}
/**
* Remove the element at a certain index.
*
* @param index
* The index of the element to be removed.
* @return The element at <code>index</code>.
* @exception ArrayIndexOutOfBoundsException
* If <code>index</code> is not a valid index.
*/
public int remove(int index) {
if (index >= this.pos) {
throw new ArrayIndexOutOfBoundsException();
}
--this.pos;
int retval = this.array[index];
for (int i = index; i < this.pos; i++) {
this.array[i] = this.array[i + 1];
}
return retval;
}
/**
* Remove all elements and set size to 0. Will not change current capacity.
*/
public void removeAllElements() {
this.pos = 0;
}
/**
* Compares the specified <code>Object</code> with this <code>IntVector</code> for equality.
* Two <code>IntVector</code>s are equal if and only if the object passed in <code>o</code>
* is of type <code>IntVector</code>, <code>this.size() == o.size()</code>, and the <i>n</i>-th
* element in this <code>IntVector</code> is equal to the <i>n</i>-th element in <code>o</code>
* for all <i>n</i> &lt; <code>this.size()</code>.
*
* @return <code>true</code> if the <code>IntVector</code>s are equal, <code>false</code>
* otherwise.
*/
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if (!getClass().equals(o.getClass())) {
return false;
}
IntVector v = (IntVector) o;
if (size() != v.size()) {
return false;
}
for (int i = 0; i < size(); i++) {
if (this.array[i] != v.get(i)) {
return false;
}
}
return true;
}
/**
* @return The number of elements in the vector.
*/
public int size() {
return this.pos;
}
/**
* Tests if the specified <code>int</code> is a component of this <code>IntVector</code>.
*
* @return <code>true</code> if and only if the <code>int</code> is an element of this
* <code>IntVector</code>, <code>false</code> otherwise.
*/
public boolean contains(int elem) {
return (position(elem) >= 0);
}
/**
* Return the position of the first occurence of <code>elem</code> in the IntVector, if it
* exists.
*
* @param elem
* The element we're looking for.
* @return The position, or <code>-1</code> if it doesn't exist.
*/
public int position(int elem) {
int i = 0;
while (i < this.pos) {
if (this.array[i] == elem) {
return i;
}
++i;
}
return -1;
}
/**
* Set every element of the vector to some value.
*
* @param value
* The fill value.
*/
public void fill(int value) {
java.util.Arrays.fill(this.array, value);
}
/**
* Return the underlying int array, where the length of the returned array is equal to the
* vector's size. This is not a copy!
*/
public int[] toArray() {
trimToSize();
return this.array;
}
/**
* Return a copy of the underlying array.
*/
public int[] toArrayCopy() {
final int max = this.size();
int[] copy = new int[max];
System.arraycopy(this.array, 0, copy, 0, max);
return copy;
}
/** Return the internal array. */
public int[] getArray() {
return this.array;
}
/**
* Returns the index of the first occurence of the element specified in this vector.
*
* @return the index or <code>-1</code> if the element was not found.
*/
public int indexOf(int element) {
int index = -1;
for (int i = 0; i < this.pos; i++) {
if (element == this.array[i]) {
index = i;
break;
}
}
return index;
}
/**
* Reduce the size of the internal array to the number of current elements. You should only use
* this if you know that your vector will not grow anymore.
*/
public void trimToSize() {
if (this.pos == this.array.length) {
return;
}
int[] new_array = new int[this.pos];
System.arraycopy(this.array, 0, new_array, 0, this.pos);
this.array = new_array;
return;
}
public IntVector copy() {
IntVector copy = new IntVector(this.array.length, this.growth_factor, this.multiplication_limit);
copy.pos = this.pos;
for (int i = 0; i < this.pos; i++) {
copy.array[i] = this.array[i];
}
return copy;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[");
for (int i = 0; i < this.pos; i++) {
if (i > 0) {
buf.append(", ");
}
buf.append(this.array[i]);
}
buf.append("]");
return buf.toString();
}
public void ensure_size(int req) {
this.array = IntArrayUtils.ensure_size(this.array, req, this.growth_factor,
this.multiplication_limit);
if (this.pos < req) {
this.pos = req;
}
}
public int hashCode() {
if (this.array == null) {
return 0;
}
int sum = 0;
for (int i = 0; i < this.size(); i++) {
sum += this.get(i);
}
return sum;
}
}