slanted W3C logo

Day 23 — Collections

A collection is an object that groups multiple object references into a single unit. You can think of a collection as representing a container for objects where each object is usually referred to as an element.

Collections

Because a collection groups multiple object references, it is an aggregation. Typically, a collection aggregates elements that form a natural group. For example:

Collection Of Represents
at most 23 hockey players National Hockey League team roster
at most 7 playing cards Texas Holdem poker hand
words dictionary
books library

Creating a Collection

Notice that some collections have a natural maximum capacity, whereas the size of other collections naturally grows and shrinks.

In the case of a collection with a known maximum capacity, it is possible to allocate enough memory to store the collection when the collection is created; this is called static allocation (where static means unchanging and is not related to the Java keyword).

In the case where the size of the collection can grow and shrink, memory is allocated as it is needed, which is called dynamic allocation. Many dynamically allocated collections have constructors that allow the client to set an initial size of the collection.

Statically Allocated Collection

The Portfolio class is an example of a statically allocated collection. It represents a collection of Investment objects.


      // no name portfolio with capacity 100
      Portfolio pf = new Portfolio();
      
      // named portfolio with capacity 50
      Portfolio myPf = new Portfolio("My Retirement Fund", 50);

Note that the capacity of a collection is different than its size. The capacity of a portfolio is the maximum number of investments that it can hold. The size of a portfolio is the actual number of investments in the portfolio.

Dynamically Allocated Collections

GlobalCredit is an example of a dynamically allocated collection. It represents a collection of credit cards (presumably distributed by a bank).


      // an empty collection of credit cards
      GlobalCredit cards = new GlobalCredit();

Some collections have constructors where the client can specify an initial capacity of the collection, but GlobalCredit does not have such a constructor.

Adding Elements

Most collections support adding elements to the collection through a method named add. Some collections place limitations on what elements may be added. Adding an element might fail if:

Failure to add an element is either indicated by the add method returning false or throwing an exception.

Adding to a Portfolio

A portfolio lets a client add investments to it until it is full (reached its capacity); otherwise, there are no restrictions on the investments that may be added.

      Portfolio pf = new Portfolio("Small Portfolio", 3);
      
      Stock stockA = new Stock("HR.A");
      Stock stockB = new Stock("HR.B");
      Stock stockC = new Stock("HR.C");
      Stock stockD = new Stock("HR.D");
      
      output.print( pf.add(new Investment(stockA, 1, 1.00)) );
      output.println( " " + pf.size() );
      
      output.print( pf.add(new Investment(stockB, 1, 2.00)) );
      output.println( " " + pf.size() );
      
      output.print( pf.add(new Investment(stockC, 1, 3.00)) );
      output.println( " " + pf.size() );
      
      output.print( pf.add(new Investment(stockD, 1, 4.00)) );
      output.println( " " + pf.size() );

The above code fragment prints:

true 1
true 2
true 3
false 3

Example: Creating a Portfolio

Try to read in a portfolio from a file as described in eCheck08B. There is a test data file on the book CD-ROM called lab8data.txt, or you can download here.

This is a good (but hard?) practice question for strings and loops.

Adding to a GlobalCredit Collection

A GlobalCredit collection will only allow unique credit cards to be added (it prevents duplicate credit cards from being in the collection); otherwise there are no restrictions on the credit cards that may be added. If a client tries to insert a credit card that is already in the collection, the add method returns false and the credit card is not added.

      GlobalCredit cards = new GlobalCredit();

      CreditCard cardA = new CreditCard(111111, "John A");
      CreditCard cardB = new CreditCard(222222, "John B");

      CreditCard cardC = new CreditCard(111111, "John C");
      // cardC.equals(cardA) == true

      CreditCard cardD = cardB;
      // cardD.equals(cardB) == true

      output.print(  cards.add(cardA)  );
      output.println( " " + cards.size() );
        
      output.print(  cards.add(cardB)  );
      output.println( " " + cards.size() );
         
      output.print(  cards.add(cardC)  );
      output.println( " " + cards.size() );
         
      output.print(  cards.add(cardD)  );
      output.println( " " + cards.size() );

The above code fragment prints:

true 1
true 2
false 2
false 2

Example: Creating a GlobalCredit Collection

Write a loop that repeatedly adds credit cards to a GlobalCredit Collection. Your program should ask for the credit card number and a name each time, and it should stop when the user enters a negative number. For "fun" you should read in the number as a string. Your program should print a warning if the credit card is already in the collection.

      GlobalCredit gcc = new GlobalCredit();
      
      output.print("Credit card number and name : ");
      int number = Integer.parseInt(input.next());
      String name = input.next();
      for (; number >= 0; )
      {
         if (!gcc.add( new CreditCard(number, name) ))
         {
            output.println("Card already exists, call police");
         }
         output.print("Credit card number and name : ");
         number = Integer.parseInt(input.next());
         name = input.next();
      }

Traversal

Many tasks require that the client do something with each element in a collection. This means that the collection must provide a mechanism for allowing the client to access each element.

Some collections provide indexed access. You can imagine that each element can be identified by a unique non-negative integer index between 0 and size - 1 where size is the number of elements in the collection (not the capacity). In Java, the client usually uses a method named get for indexed access:

      Portfolio pf = Portfolio.getRandom();
      
      Investment first = pf.get(0);
      output.println( first.getStock() );

To perform a traversal, the client writes a loop:

      Portfolio pf = Portfolio.getRandom();
      double pfBookValue = 0.0;
      double pfCurrentValue = 0.0;
      
      for (int i = 0; i < pf.size(); i++)
      {
         Investment inv = pf.get(i);
         double bookValue = inv.getQty() * inv.getBookValue();
         double currentValue =
            inv.getQty() * inv.getStock().getPrice();
            
         pfBookValue += bookValue;
         pfCurrentValue += currentValue;
      }
      output.printf("Book Value    : $%.2f%n", pfBookValue);
      output.printf("Current Value : $%.2f%n", pfCurrentValue);

To Do For Next Lecture