Flexible Arrays in Java

This page contains course notes for Object Oriented Programming taught in the Spring of 2011. If you have come here from a search engine or the like, you may wish to visit the course home page for more material, or visit my general teaching page for possibly more up to date versions, or perhaps my home page

  1. Right now new we have two choices for representing lists of data:
    1. Arrays
    2. Linked Lists
  2. Arrays have the problem that they're difficult to add to, especially when the array is full.
  3. Linked lists have the problem that to access an arbitrary item, you need to walk the length of the list.
  4. There is another option in Java, the ArrayList.
  5. The ArrayList is a class that is implemented as an array, so you can get to elements easily, but it will automatically resize the array if you fill it up so that you can easily add stuff and not have to worry about "resizing" the array. (what would it take to resize an array?)
  6. Using it looks something like this:
    ArrayList myList = new ArrayList();
    myList.add(new Book("A Shore Thing")); //appends new book to myList
    myList.add(new Book("The Rules According to JWOWW"));
    Book b = myList.get(0);
    
  7. There a problem here though. Since the ArrayList class has an array in it, how does the code know what type to make that array?
    1. One obvious thing is to have the array in the ArrayList be of type Object, then we can add anything to it.
      class ArrayList {
        Object [] theArray;
        //...
        Object get(int elt) {
        //...
        }
        //...
      }
      
    2. One problem with this is that it would make the program slow because it would always have to do type checking at runtime.
    3. Another problem would be that when we take things out of the ArrayList, we have to cast them to the type of object they all. The get line above would have to be: Book b = (Book) myList.get(0).
    4. What we want is some flexible type system that resolves itslef at compile time so we can limit the type inferencing, and always know the type we get out. We do this with what in Java we call "Generics". In C++ they're called Templates.
  8. The require a new syntax to tell the compiler what the type of the array should be:
    ArrayList<Book> myList = new ArrayList<Book>();
    myList.add(new Book("A Shore Thing")); //appends new book to myList
    myList.add(new Book("The Rules According to JWOWW"));
    Book b = myList.get(0);
    
  9. That's it. Now you can just use the ArrayList as if it only contains Books. We can still do Polymorphism with it if we want:
    ArrayList<Item> myList = new ArrayList<Item>();
    myList.add(new Book("A Shore Thing")); //appends new book to myList
    myList.add(new Book("The Rules According to JWOWW"));
    Item b = myList.get(0);
    
  10. How this works inside ArrayList is:
    class ArrayList<E> {
      E [] theArray;
      //...
      E get(int elt) {
      //...
      }
      //...
    }
    
  11. Java is littered with helpful classes like ArrayList that use generics. RTFM.
  12. Many of these classes implement a special interface, that enables us to loop through them easily. The interface is the "Iterable" interface:
    interface Iterable<E> { //...
    
  13. For any class that correctly implements the Iterable interface, you can loop across it with the "foreach" loop:
    ArrayList<MovingObject> inv = new ArrayList<MovingObject>();
          //...
    for (MovingObject m : inv) {
        System.out.println(m);
    }
    
  14. each pass through the loop, the variable (in this case m) takes the value of the next item in the ArrayList.
  15. Many built-in classes implement Iterable:
    LinkedList<Student> classOf11 = new LinkedList<Student>();
          //...
    for (Student s:classOf11) {
          s.placeOnRestriction();
    }