tags:

views:

106

answers:

5

Given

private final Vector v = new Vector();  //instance variable

the following 3 lines are in an instance method in the same class.

1.    int length = v.capacity();   
2.    int size = v.size();
3.    Object o = v.getElementAt(0);

I am getting an ArrayIndexOutOfBoundsException at line 3.

The debugger shows that the Vector has 10 elements.
length shows 10.
size shows 0.

Why is this exception being thrown, do I need to do a setSize() to use the Vector v?

+2  A: 

No, but you do have to add an element before you get it.

Vector is old school Java 1.0. It uses synchonrization as its default, which can affect your performance. Why are you not considering the newer java.util.List and java.util.ArrayList classes?

duffymo
Actually the vector is being supplied elements by another thread and a 2nd thread is reading the elements. I was trying to check the Object o for null after v.getElementAt(0). Isn't that the right way to go?
Kevin Boyd
As said to extraneon, using this in J2ME, also edited tag in question.
Kevin Boyd
+1  A: 

No. The vector has reserved space for 10 elements. But it doesn't yet contain any of those elements you need to add something to the vector using 'put'

Length will tell you the amount of reserved space, size tells you how much you can actually use.

Vectors typically reserve more space than they need as an optimisation

Glen
What is the solution to the above problem do i have to do a v.isEmpty() before using the vector. Also read my answer to duffymo regarding threading.
Kevin Boyd
+1  A: 

The capacity is the space allocated for current and future elements, an internal (to the vector) number which is exposed for performance reasons. The capacity is equal to or larger than the amount of elements it contains.

The size() shows you how many elements you put in the vector. The capacity is more in the nature of internal bookkeeping of the vector. You can only get elements 0... getSize() -1 out of the vector.

That said, if you don't use the data in multiple threads it's probably better to use ArrayList.

You can check whether the vector is empty by using isEmpty(), which should do something like getSize() == 0.

extraneon
Am actually using this in Java ME/CLDC1.0 which doesn't have the ArrayList class.
Kevin Boyd
+2  A: 

The capacity() method tells you have many elements the Vector can take, before it has to increase its capacity. It doesn't tell you have many elements that currently is in the Vector, that's what size() is assigned to do. And in your case it does, since the Vector is empty.

You can specify the capacity by providing parameters to the constructor:

Vector v = new Vector(20);
/* This vector will have the starting capacity
   of 20 elements, before it has to increase
   its capacity */


Vector v = new Vector(10, 5);
/* This vector will have an initial capacity
   of 10 elements, and when it overflows the
   second parameter tells the vector to increase
   its capacity by 5. */

Edit

Based on your comments to other posts, it seems that you have two threads in your application - where one puts stuff into the vector and another one reads the vector?

Then you have to add a control structure to check wether the vector is empty or not, before trying to get elements from it.

Dirty example:

/* Vector instantiation goes here */

boolean keepRunningFlag = true;
while(keepRunningFlag) {
    if (!vector.isEmpty()) {
        Object o = vector.remove(vector.size() - 1);
        keepRunningFlag = doStuffWithVectorElement(o);
    }
}
Björn
+1  A: 

As several people have mentioned, you don't want to look at the Vector's capacity, or (equivalently) the length of its internal array. In practice, you almost never want to look at the capacity of a Vector. You need to use size() (or isEmpty(), which returns true if and only if size() returns 0).

Attempting to call getElementAt(x) on an element that isn't there does not return null. It throws an exception.

Since you've got another thread inserting elements, you probably want to check the size and retrieve the element atomically. Actually, it sounds like you're trying to implement a producer/consumer queue, in which case you want to also remove the element as part of the same atomic operation. The most straightforward way to do this is to synchronize on the Vector. eg:

Object o = null;
synchronized(v) {
    if (!v.isEmpty()) {
        o = v.getElementAt(0);
        v.removeElementAt(0);
    }
}
// at this point the first element of the vector will be removed
// (if there was one) and o be pointing at that first element. If
// the Vector was empty, o will still be null.

A few caveats with this code:

  • if v gets large, this becomes inefficient, because removing the first element in a Vector shifts all of the remaining elements over by one. If this is an issue for you you may want to find or write a queue class.
  • If a null is inserted in the Vector o will also be set to null. That may or may not be an issue for you.
Laurence Gonsalves