1. Vectors
    1. Vector Specification
    2. Assignment 2
    3. Josephus
  2. Vector implementation
    1. Increasing space in vector

Vectors

Last time talked about the use of arrays.

Can create arrays of any fixed size, but can't change size aside from creating an entirely new array.

Vector Specification

Built-in class Vector allows user to build something like an array, but can change size dynamically. Can add new elts or delete elts anywhere in vector.

Vector holds elements of type Object, hence must use casts when take out elements to do anything useful with them (unlike arrays!)

Below is listing of many of methods in implementation of Vector in structure library (which mimics the one in java.utilities).

public class Vector
{
    // post: constructs a vector with capacity for 10 elements
    public Vector()

    // pre: initialExtent >= 0
    // post: constructs an empty vector with initialExtent 
    //  capacity
    public Vector(int initialExtent)

    // pre: initialExtend >= 0, extentIncrement >= 0
    // post: constructs an empty vector with initialExtent 
    //  capacity that extends capacity by extentIncrement, or 
    //  doubles if 0
    public Vector(int initialExtent, int extentIncrement)

    // post: adds new element to end of possibly extended 
    //  vector
    public void addElement(Object obj)
 
    // post: returns true iff Vector contains the value
    //  (could be faster, if orderedVector is used)
    public boolean contains(Object elem)

    // pre: dest has at least size() elements
    // post: a copy of the vector is stored in the dest array
    public void copyInto(Object dest[])

    // pre: 0 <= index && index < size()
    // post: returns the element stored in location index
    public Object elementAt(int index)

    // pre: vector contains an element
    // post: returns first value in vector
    public Object firstElement()
 
    // post: returns index of element equal to object, or -1.  
    //  Starts at 0.
    public int indexOf(Object elem)

    // post: returns index of element equal to object, or -1.  
    //  Starts at index.
    public int indexOf(Object elem, int index)

    // pre: 0 <= index <= size()
    // post: inserts new value in vector with desired index
    //   moving elements from index to size()-1 to right
    public void insertElementAt(Object obj, int index)

    // post: returns true iff no elements in the vector
    public boolean isEmpty()
 
    // pre: vector is not empty
    // post: returns last element of the vector
    public Object lastElement()
  
    // post: returns index of last occurrence of object in the 
    //  vector, or -1
    public int lastIndexOf(Object obj)

    // pre: index >= 0
    // post: returns the index of last occurrence of object at  //  or before index.
    public int lastIndexOf(Object obj, int index)
  
    // post: vector is empty
    public void clear()

    // post: vector is empty
    public void removeAllElements()
 
    // post: remove first element of vector equal to parameter 
    //  Move later elts back to fill space.
    public boolean removeElement(Object element)

    // pre: 0 <= where && where < size()
    // post: indicated element is removed, size decreases by 1
    public void removeElementAt(int where)

    // pre: 0 <= index && index < size()
    // post: element value is changed to obj
    public void setElementAt(Object obj, int index)

    // post: returns the size of the vector
    public int size()
}

Vectors are generally used any time size of an array must change dynamically.

A vector can hold any object. Thus can write myVect.addElt("Hello"). But notice when withdraw an elt (e.g., myVect.firstElement()), type is Object. Therefore must cast back to original value. Therefore write:

        String val = (String)myVect.firstElement();
Annoying, but must be done.

Cannot store base types in Vector since base types are not objects. Luckily, there is a method to wrap them up as Objects:

   Integer seven = new Integer(7);
Others are Boolean, Character, Double, Float, Long, Number

Can get int equivalent by sending the "intValue" message: seven.intValue();

Can find the entire list of classes and associated methods in the java.lang package documentation.

One example of using Vectors is in paint programs where new objects added. See SimpleDraw.

Assignment 2

Write CircularVector class which implements Circular. Write a test program in main procedure of CircularVector to ensure it works. Then can link it into my Josephus program to use it there.

Josephus

Look first at RectElt in Assn 2 folder to see how objects of game are represented, and the methods available. Note that this depends on my graphics library (documentation available through CS136 web pages). Then look at Josephus.java. Ignore set-up info in init() method. Focus instead on initializeList() and findMessenger()

Vector implementation

How can we implement Vector?

Might try linked list or some sort of array.

Try array implementation. Vector has two fields, array and # elts of array currently in use.
Note distinction btn size of array and # elts in use!

When about to exceed capacity, copy elts into a larger array.
Need efficient strategy for this.

Following is simplification from (more complex) code in structures:

public class Vector 
{
    protected Object elementData[]; // the data
    protected int elementCount;     // # of elts in vec
    protected int capacityIncrement;    // the rate of growth for 
                                                // vector

    // pre: initialExtend >= 0, extentIncrement >= 0
    // post: construct empty vector with initialExtent capacity
    //  that extends capacity by extentIncrement, or doubles 
    //  if 0
    public Vector(int initialExtent, int extentIncrement)
    {
        Assert.pre(initialExtent >= 0, 
                                        "Non-negative vector extent.");
        elementData = new Object[initialExtent];
        elementCount = 0;
        capacityIncrement = extentIncrement;
    }

Accessing and modifying elts trivial, adding and deleting more tricky. Method ensureCapacity(int n) ensures there is space for at least n elts in array component of vector. (Will discuss in detail later.)

    // post: add new element to end of possibly extended vector
    public void addElement(Object obj)
    {
        ensureCapacity(elementCount+1);
        elementData[elementCount] = obj;
        elementCount++;
    }

    // pre: 0 <= index <= size()
    // post: inserts new value in vector with desired index
    //   moving elements from index to size()-1 to right
    public void insertElementAt(Object obj, int index)
    {
        int i;
        ensureCapacity(elementCount+1);
        // Must copy from right to left to avoid destroying data
        for (i = elementCount; i > index; i--) 
            elementData[i] = elementData[i-1];
        // assertion: i == index and element[index] is available
        elementData[index] = obj;
        elementCount++;
    }

Remove similar (see code on line).

Adding or deleting an element may involve moving up to n elts, if n elts in array (slow!!).

Increasing space in vector

What if run out of space in the array when adding new elts?

Options:

1. Make new array with 1 (or some fixed # of) more elts and copy old array into new.

2. Make new array with double (or triple, ...) # of elts and copy old into new.

First option bad, since if start w/ empty takes about n2/2 copies to add n elts to vector.

(0 + 1 + 2 + 3 + 4 + ... + n = n*(n-1)/2 )

Whereas no copies need to be made if allocated space for n elts at beginning.

With second option (where assume n is power of 2 for simplicity), copy

0 + 1 + 2 + 4 + 8 + ... + n/2 = n - 1 elts.

While this is overhead, extra copy of n elts, much less painful than n2/2.

Let user decide which strategy to use. If call Vector(int initialExtent) then set capacityIncrement to 0 and use doubling strategy, else always extend by capacityIncrement new elts:

    // post: capacity of this vector is at least minCapacity.
    public void ensureCapacity(int minCapacity)
    {
        if (elementData.length < minCapacity) 
        {           // have less than needed
            int newLength = elementData.length; // initial guess
            if (capacityIncrement == 0) 
            {   // increment of 0 suggests doubling (default)
                if (newLength == 0) newLength = 1;
                while (newLength < minCapacity) 
                    newLength = newLength * 2;
            } 
            else 
            {   // increment != 0 suggests incremental increase
                while (newLength < minCapacity)
                    newLength = newLength + capacityIncrement;
            }
            // assertion: newLength > elementData.length.
            Object newElementData[] = new Object[newLength];
            // copy old data to array
            for (int i = 0; i < elementCount; i++) 
                newElementData[i] = elementData[i];
            elementData = newElementData;
            // N.B. Garbage collector will pick up old elementData
        }
        // assertion: capacity is at least minCapacity
    }