Getting ArrayOutOfBoundsException - java

  • Comp Sci
  • Thread starter schapman22
  • Start date
  • Tags
    Java
In summary: NullPointerException * @throws IllegalArgumentException * @throws OutOfMemoryError if this bag cannot hold the new element. **/ /** * Remove the first element from this bag. * @param element * the element to be removed from the bag. * @return the element that was removed, or null if the remove operation failed. * @throws NullPointerException *
  • #1
schapman22
74
0

Homework Statement



I am supposed to write a program that has the user enter 10 nouns and 10 verbs. It then creates a 4 sentence story using the those words. I am getting an ArrayOutOfBoundsException when it gets to the part where it prints out the story. The exception is found in the grab() method of ArrayBag. I can't figure out the issue though.

Homework Equations



Code:
// File: ArrayBag.java from the package edu.colorado.collections
// Additional javadoc documentation is available from the ArrayBag link in:
//   http://www.cs.colorado.edu/~main/docs

package edu.colorado.collections;

/******************************************************************************
* An ArrayBag is a generic collection of references to objects.
* The same object may appear multiple times in a bag.
*
* @note
*   (1) The capacity of one of these bags can change after it's created, but
*   the maximum capacity is limited by the amount of free memory on the 
*   machine. The constructor, addItem, clone, 
*   and union will result in an OutOfMemoryError
*   when free memory is exhausted.
*   <p>
*   (2) A bag's capacity cannot exceed the maximum integer 2,147,483,647
*   (Integer.MAX_VALUE). Any attempt to create a larger capacity
*   results in a failure due to an arithmetic overflow. 
*   <p>
*   (3) Because of the slow linear algorithms of this
*   class, large bags will have poor performance.
*
* @see
*   <A HREF="../../../../edu/colorado/collections/ArrayBag.java">
*   Java Source Code for this class
*   (www.cs.colorado.edu/~main/edu/colorado/collections/ArrayBag.java)
*   </A>
*
* @author Michael Main 
*   <A HREF="mailto:main@colorado.edu"> (main@colorado.edu) </A>
*
* @version
*   Jul 5, 2005
*
* @see IntArrayBag
* @see LinkedBag
******************************************************************************/
public class ArrayBag<E> implements Cloneable
{
   // Invariant of the ArrayBag class:
   //   1. The number of elements in the bag is in the instance variable 
   //      manyItems, which is no more than data.length.
   //   2. For an empty bag, we do not care what is stored in any of data;
   //      for a non-empty bag, the elements in the bag are stored in data[0]
   //      through data[manyItems-1], and we don't care what's in the
   //      rest of data.
   private E[ ] data;
   private int manyItems; 
   
   /**
   * Initialize an empty bag with an initial capacity of 10.  Note that the
   * addItem method works efficiently (without needing more
   * memory) until this capacity is reached.
   * @param - none
   * @postcondition
   *   This bag is empty and has an initial capacity of 10.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for: 
   *   new Object[10].
   **/   
   public ArrayBag( )
   {
      final int INITIAL_CAPACITY = 10;
      manyItems = 0;
      data = (E[]) new Object[INITIAL_CAPACITY];
   }
     

   /**
   * Initialize an empty bag with a specified initial capacity. Note that the
   * addItem method works efficiently (without needing more
   * memory) until this capacity is reached.
   * @param initialCapacity
   *   the initial capacity of this bag
   * @precondition
   *   initialCapacity is non-negative.
   * @postcondition
   *   This bag is empty and has the given initial capacity.
   * @exception IllegalArgumentException
   *   Indicates that initialCapacity is negative.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for: new Object[initialCapacity].
   **/   
   public ArrayBag(int initialCapacity)
   {
      if (initialCapacity < 0)
         throw new IllegalArgumentException
         ("The initialCapacity is negative: " + initialCapacity);
      data = (E[]) new Object[initialCapacity];
      manyItems = 0;
   }
        
 
   /**
   * Add a new element to this bag. If the new element would take this
   * bag beyond its current capacity, then the capacity is increased
   * before adding the new element.
   * @param element
   *   the new element that is being inserted
   * @postcondition
   *   A new copy of the element has been added to this bag.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for increasing the bag's capacity.
   * @note
   *   An attempt to increase the capacity beyond
   *   Integer.MAX_VALUE will cause the bag to fail with an
   *   arithmetic overflow.
   **/
   public void add(E element)
   {
      if (manyItems == data.length)
      {  // Ensure twice as much space as we need.
         ensureCapacity((manyItems + 1)*2);
      }

      data[manyItems] = element;
      manyItems++;
   }


   /**
   * Add new elements to this bag. If the new elements would take this
   * bag beyond its current capacity, then the capacity is increased
   * before adding the new elements.
   * @param elements
   *   (a variable-arity argument)
   *   one or more new elements that are being inserted
   * @postcondition
   *   A new copy of the element has been added to this bag.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for increasing the bag's capacity.
   * @note
   *   An attempt to increase the capacity beyond
   *   Integer.MAX_VALUE will cause the bag to fail with an
   *   arithmetic overflow.
   **/
   public void addMany(E... elements)
   {
      if (manyItems + elements.length > data.length)
      {  // Ensure twice as much space as we need.
         ensureCapacity((manyItems + elements.length)*2);
      }

      System.arraycopy(elements, 0, data, manyItems, elements.length);
      manyItems += elements.length;
   }


   /**
   * Add the contents of another bag to this bag.
   * @param addend
   *   a bag whose contents will be added to this bag
   * @precondition
   *   The parameter, addend, is not null. 
   * @postcondition
   *   The elements from addend have been added to this bag.
   * @exception NullPointerException
   *   Indicates that addend is null. 
   * @exception OutOfMemoryError
   *   Indicates insufficient memory to increase the size of the bag.
   * @note
   *   An attempt to increase the capacity beyond
   *   Integer.MAX_VALUE will cause an arithmetic overflow
   *   that will cause the bag to fail. Such large collections should use
   *   a different bag implementation.
   **/
   public void addAll(ArrayBag<E> addend)
   {
      // If addend is null, then a NullPointerException is thrown.
      // In the case that the total number of items is beyond
      // Integer.MAX_VALUE, there will be an arithmetic overflow and
      // the bag will fail.
      ensureCapacity(manyItems + addend.manyItems);
         
      System.arraycopy(addend.data, 0, data, manyItems, addend.manyItems);
      manyItems += addend.manyItems;
   }   
   
   
   /**
   * Generate a copy of this bag.
   * @param - none
   * @return
   *   The return value is a copy of this bag. Subsequent changes to the
   *   copy will not affect the original, nor vice versa.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for creating the clone.
   **/ 
   public ArrayBag<E> clone( )
   {  // Clone an ArrayBag object.
      ArrayBag<E> answer;
      
      try
      {
         answer = (ArrayBag<E>) super.clone( );
      }
      catch (CloneNotSupportedException e)
      {  // This exception should not occur. But if it does, it would probably
         // indicate a programming error that made super.clone unavailable.
         // The most common error would be forgetting the "Implements Cloneable"
         // clause at the start of this class.
         throw new RuntimeException
         ("This class does not implement Cloneable");
      }
      
      answer.data = data.clone( );
      
      return answer;
   }
   

   /**
   * Accessor method to count the number of occurrences of a particular element
   * in this bag.
   * @param target
   *   the element that needs to be counted
   * @return
   *   the number of times that target occurs in this bag
   **/
   public int countOccurrences(E target)
   {
      int answer;
      int index;
      
      answer = 0;
      for (index = 0; index < manyItems; index++)
         if (target == data[index])
            answer++;
      return answer;
   }


   /**
   * Change the current capacity of this bag.
   * @param minimumCapacity
   *   the new capacity for this bag
   * @postcondition
   *   This bag's capacity has been changed to at least minimumCapacity.
   *   If the capacity was already at or greater than minimumCapacity,
   *   then the capacity is left unchanged.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for: new Object[minimumCapacity].
   **/
   public void ensureCapacity(int minimumCapacity)
   {
      E biggerArray[ ];
      
      if (data.length < minimumCapacity)
      {
         biggerArray = (E[]) new Object[minimumCapacity];
         System.arraycopy(data, 0, biggerArray, 0, manyItems);
         data = biggerArray;
      }
   }

   
   /**
   * Accessor method to get the current capacity of this bag. 
   * The add method works efficiently (without needing
   * more memory) until this capacity is reached.
   * @param - none
   * @return
   *   the current capacity of this bag
   **/
   public int getCapacity( )
   {
      return data.length;
   }

              
   /**
   * Accessor method to retrieve a random element from this bag.
   * @param - none
   * @precondition
   *   This bag is not empty.
   * @return
   *   a randomly selected element from this bag
   * @exception IllegalStateException
   *   Indicates that the bag is empty.
   **/
   public E grab( )
   {
      int i;
      
      if (manyItems == 0)
         throw new IllegalStateException("Bag size is zero");
         
      i = (int)(Math.random( ) * manyItems) + 1;
      return data[i];
   }
   
             
   /**
   * Remove one copy of a specified element from this bag.
   * @param target
   *   the element to remove from the bag
   * @postcondition
   *   If target was found in the bag, then one copy of
   *   target has been removed and the method returns true. 
   *   Otherwise the bag remains unchanged and the method returns false. 
   **/
   public boolean remove(E target)
   {
      int index; // The location of target in the data array.
       
      // First, set index to the location of target in the data array,
      // which could be as small as 0 or as large as manyItems-1; If target
      // is not in the array, then index will be set equal to manyItems;
      if (target == null)
      {  // Find the first occurrence of the null reference in the bag.
	 index = 0;
	 while ((index < manyItems) && (data[index] != null))
            index++;
      }
      else
      {  // Find the first occurrence of the target in the bag.
	 index = 0;
	 while ((index < manyItems) && (!target.equals(data[index])))
            index++;
      }

      if (index == manyItems)
         // The target was not found, so nothing is removed.
         return false;
      else
      {  // The target was found at data[index].
         // So reduce manyItems by 1 and copy the last element onto data[index].
         manyItems--;
         data[index] = data[manyItems];
	 data[manyItems] = null;
         return true;
      }
   }
                 
   
   /**
   * Determine the number of elements in this bag.
   * @param - none
   * @return
   *   the number of elements in this bag
   **/ 
   public int size( )
   {
      return manyItems;
   }
   
   
   /**
   * Reduce the current capacity of this bag to its actual size (i.e., the
   * number of elements it contains).
   * @param - none
   * @postcondition
   *   This bag's capacity has been changed to its current size.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for altering the capacity. 
   **/
   public void trimToSize( )
   {
      E trimmedArray[ ];
      
      if (data.length != manyItems)
      {
         trimmedArray = (E[]) new Object[manyItems];
         System.arraycopy(data, 0, trimmedArray, 0, manyItems);
         data = trimmedArray;
      }
   }
      

   /**
   * Create a new bag that contains all the elements from two other bags.
   * @param b1
   *   the first of two bags
   * @param b2
   *   the second of two bags
   * @precondition
   *   Neither b1 nor b2 is null, and
   *   b1.getCapacity( ) + b2.getCapacity( ) &lt;= Integer.MAX_VALUE.
   * @return
   *   the union of b1 and b2
   * @exception NullPointerException.
   *   Indicates that one of the arguments is null.
   * @exception OutOfMemoryError
   *   Indicates insufficient memory for the new bag.
   * @note
   *   An attempt to create a bag with a capacity beyond
   *   Integer.MAX_VALUE will cause an arithmetic overflow
   *   that will cause the bag to fail. Such large collections should use
   *   a different bag implementation.
   **/   
   public static <E> ArrayBag<E> union(ArrayBag<E> b1, ArrayBag<E> b2)
   {
      // If either b1 or b2 is null, then a NullPointerException is thrown. 
      // In the case that the total number of items is beyond
      // Integer.MAX_VALUE, there will be an arithmetic overflow and
      // the bag will fail.   
      ArrayBag<E> answer = new ArrayBag<E>(b1.getCapacity( ) + b2.getCapacity( ));
      
      System.arraycopy(b1.data, 0, answer.data, 0, b1.manyItems);
      System.arraycopy(b2.data, 0, answer.data, b1.manyItems, b2.manyItems);
      answer.manyItems = b1.manyItems + b2.manyItems;
      
      return answer;
   }
   
   public void printList()
   {
       for(int i=0; i<manyItems; i++)
       {
           System.out.println(this.data[i]);
       }
   }
      
}

The Attempt at a Solution



Code:
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.colorado.collections;

/**
 *
 * @author Scott
 */
import java.util.Scanner;
public class Story 
{
    private static Scanner keyboard = new Scanner(System.in);

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) 
    {
        final int WORDS_PER_BAG = 10;
        final int MANY_SENTENCES = 4;
        
        ArrayBag<String> nouns = new ArrayBag<>(WORDS_PER_BAG);
        ArrayBag<String> verbs = new ArrayBag<>(WORDS_PER_BAG);
        int line;
        
        System.out.println("Help me write a silly story.\n");
        getWords(nouns, WORDS_PER_BAG, "nouns");
        getWords(verbs, WORDS_PER_BAG, "verbs");
        System.out.println("Thank you for your assistance.\n");
        
        System.out.println("Silly Story\n");
        for(line=1; line<=MANY_SENTENCES; line++)
        {
            System.out.print("The " + (String)nouns.grab() + " ");
            System.out.print((String)verbs.grab());
            System.out.println(" the " + (String)nouns.grab() + ".");
        }
        
        
        
        
    }
    
    public static void getWords(ArrayBag<String> b, int n, String prompt)
    {
        String userInput;
        int i;
        
        System.out.print("Please type " + n + " " + prompt);
        System.out.println(", separated by spaces.");
        System.out.println("Press the <return> key after final entry:");
        for( i=1; i<=n; i++)
        {
            userInput = keyboard.next();
            b.add(userInput);
        }
        System.out.println();
    }
}
 
Physics news on Phys.org
  • #2
Is the ArrayBag provided code that is supposed to work fine, or was this something that you wrote as well? The most helpful, and likely easier method would be to use a debugger. Set a breakpoint at
Code:
i = (int)(Math.random( ) * manyItems) + 1;
and see that data has items, and that i doesn't go outside the size (which it must be, since you're getting ArrayIndexOutOfBounds).
 
  • #3
It was written by the author of my textbook. I tried changing the code to
Code:
i = (int)(Math.random( ) * manyItems);
And it did solve my problem, but I can't understand why it was even causing problem.
 
  • #4
Well, I didn't look at when manyItems was updated, but if it is like array.size (or whatever Java calls it), then because arrays are zero-indexed, you loop or access from array.size - 1 or use a strictly less than test. Do you see why that is?

Aside, that's an odd way to get a random out of an array, in my opinion. I like Python's method http://docs.python.org/library/random.html#random.choice
 
  • #5
Yeah it does make sense not to add 1. I wonder why he wrote it like that.
 

1. "What is an ArrayOutOfBoundsException in Java?"

An ArrayOutOfBoundsException is an error that occurs when a program attempts to access an element in an array at an index that is outside of the array's bounds. This typically happens when the index is either negative or greater than or equal to the length of the array.

2. "What causes an ArrayOutOfBoundsException to occur?"

There are a few different reasons why an ArrayOutOfBoundsException may occur in Java. One common cause is attempting to access an index that is outside of the array's bounds, as mentioned in the previous question. Another cause could be using an incorrect index when trying to retrieve or modify an element in the array. Additionally, if the array is not properly initialized or has a size of 0, an ArrayOutOfBoundsException may also be thrown.

3. "How can I fix an ArrayOutOfBoundsException in Java?"

The best way to fix an ArrayOutOfBoundsException is to carefully review the code and make sure that the index being used to access the array is within the bounds of the array. You can also use conditional statements to check the length of the array before attempting to access an element. Another solution could be to use a different data structure, such as an ArrayList, which allows for dynamic resizing and can help avoid this error.

4. "Is an ArrayOutOfBoundsException a runtime or compile-time error?"

An ArrayOutOfBoundsException is a runtime error, meaning it occurs during the execution of the program rather than during compilation. This means that the error may not be detected until the program is actually running, making it important to thoroughly test code that involves arrays to prevent this error from occurring.

5. "Can I prevent an ArrayOutOfBoundsException from occurring in my Java program?"

While it is not possible to completely prevent an ArrayOutOfBoundsException from occurring, there are steps you can take to minimize the chances of it happening. These include carefully reviewing and testing code that involves arrays, using conditional statements to check the length of the array before accessing elements, and considering alternative data structures that may be more suitable for your program's needs.

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
2
Views
5K
  • Engineering and Comp Sci Homework Help
Replies
3
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
12
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
4
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
11
Views
11K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
2K
  • Programming and Computer Science
Replies
8
Views
1K
Back
Top