Return to lecture notes index

15-100 Lecture 22 (Wednesday, November 1, 2006)

Quick Quiz

//Note: You are given a Car class specification, which includes a static method as follows:
//   public static Car Car.getNextCar();

// SPECIAL RESTRICTION: You may call print()/println() at MOST (and probably fewer) three times. 

// 1. Create a new array of 10 Car references called "cars"
Car[] cars = new Car[10];

// 2. Populate the array with 10 Cars using the Car.getNextCar() method as described above
for (int index=0; index < 10; index++) {
  cars[index] = Car.getNextCar();
}

// 3. Print the even-indexed cars (including the 0th Car) in the "forward" order
for (int index=0; index < 10; index+=2)
  System.out.println (cars[index]);

// 3, alternative (but ugly)
for (int index=0; index < 10; index++) {
  if ((index % 2) == 0)
    System.out.println (cars[index]);
}


// 4. Print the odd-indexed cars in the reverse order.
for (int index=9; index >= 1; index -= 2) {
  System.out.println (cars[index]);
}

Today's Example

Today, we're going to create a contains method and write some special add methods. This should help you understand how things are placed into arrays and some ways to manipulate the data stores inside.

The contains(...) Method

The contains(...) method is really an extension of the same traveral we used for toString(). We walk through each item within the Collection, from [0...(.length-1)]. The only difference is that, for each item, we check to see if it matches the one for which we are searching using equals(). If it does, we immediately return true -- we are done, there is no reason to continue the traversal. If however we work our way through the entire array and don't find a match, we return false -- there is no where else to look.

  public boolean contains (Object item) {
  
    for (int index=0; index < nextSlot; index++) {
      if (items[index].equals(item)) 
        return true;
    }
    
    return false;
  
  }

Add Last and Add First

The add last method is what we have been doing up until now, inserting the item at the very end of the array. So what's different about inserting an item into the beginning of the array?

Well, we can't just set items[0] equal to the item we're inserting. This is because whatever was at items[0] would just get overwritten. So what we have to do is shift everything over in the array to make space for the new item. The easiest way to do this is to start at the end of the array and start pulling stuff over. In array of n items, count will be equal to n and we'll have the last item stored at n-1 (0, 1, 2... n-1 are our indicies). So this means that index n should be an empty space (unless the array is full, in which case we'll grow() just like our normal add method). So we need to start at n and and set index[n] equal to index[n-1], then do the same thing for n-1. We do this index[n-1] = index[n-2] all the way until index[1] = index[0], in which case we've shifted everything over and we go ahead and set items[0] equal to our item being inserted. Let's take a look at some code:


  public void addFirst(Object o) {
    if (count == items.length)
      grow();
  
    for (int holeIndex=count; holeIndex > 0; holeIndex--) {
      items[holeIndex] = items[holeIndex-1];
      items[holeIndex-1] = null;
    }
    
    items[0] = o;
    
    count++;
   }

Add Before

This method will take in two items, an item to insert, and an item to insert before. This will look similar to our AddFirst method in the sense that we have to shift items over to make room, since we're not adding to the end of the array again.

Again, we'll start at the end of the array and walk backwards, shifting items over. The difference is that this time we want to stop after we've shifted the item to insert before. For example if we try to insert D before E in the following example:

	
	0 1 2 3 4 5
	A B C E F

	5 is our index so we
	set items[5] to items[4]
	0 1 2 3 4 5
	A B C E F F

	4 is our index so we
	set items[4] to items[3]
	0 1 2 3 4 5
	A B C E E F

	items[4] is equal to E
	so we stop shifting items over
	and insert at items[3]
	0 1 2 3 4 5
	A B C D E F

Notice that when we shift items over, we don't "get rid of" or set to null the old index so we end up with two spots have F in them. This is because we know that in the next step, the original F will be overwritten. This process continues all the way until we find the item to insert before (E) in which case the item to insert takes the place of the original E.

We'll make this method return type boolean because its possible that the item to insert before is not within our array in which case we can't perform the requested operation.

 public boolean addBefore (Object addMe, Object beforeMe) {
   
     if (!contains(beforeMe)) return false;
     
     if (count == items.length)
      grow();
 
     int holeIndex=-1;
     for (holeIndex=count-1;    ; holeIndex--) {
       items[holeIndex+1] = items[holeIndex];
       if (items[holeIndex+1].equals(beforeMe))
         break;
     }
     
     items[holeIndex] = addMe;
     count++;

     return true;
   
   }

Container, so far

class ArrayCollection {

  private Object[] items;
  private int count;
  
  private static final int DEFAULT_SIZE = 100;
  private static final int GROWTH_COEFF = 2;
  
  
  private void grow() {
    Object[] biggerArray = new Object[GROWTH_COEFF * items.length];
  
    for (int index=0; index < items.length; index++)
      biggerArray[index] = items[index];
  
    items = biggerArray;
  }
  
  
  public ArrayCollection(int size) {
    items = new Object[size];
    count = 0;
  }
  
  
  public ArrayCollection() {
    items = new Object[DEFAULT_SIZE];
    count = 0;
  }
  
  
  public void addLast(Object item) {
    if (count == items.length)
      grow();
  
    items[count++] = item;
  }


  public void addFirst(Object o) {
    if (count == items.length)
      grow();
  
    for (int holeIndex=count; holeIndex > 0; holeIndex--) {
      items[holeIndex] = items[holeIndex-1];
      items[holeIndex-1] = null;
    }
    
    items[0] = o;
    
    count++;
   }
   
   public boolean addBefore (Object addMe, Object beforeMe) {
   
     if (!contains(beforeMe)) return false;
     
     if (count == items.length)
      grow();
 
     int holeIndex=-1;
     for (holeIndex=count-1;    ; holeIndex--) {
       items[holeIndex+1] = items[holeIndex];
       if (items[holeIndex+1].equals(beforeMe))
         break;
     }
     
     items[holeIndex] = addMe;
     count++;

     return true;
   
   }
   
   
   


  public boolean contains (Object o)  {
    
    for (int index=0; index < count; index++)
      if (items[index].equals(o)) return true;
    
    return false;
  }
  
  
  


}