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.
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:
null
Failure to add an element is either indicated by the add
method returning false
or throwing an exception.
Recall that a Portfolio
is a statically
allocated collection (has a fixed capacity).
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.
Consider a Portfolio
with capacity 3:
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
GlobalCredit
Collection
Recall that GlobalCredit
is a dynamically
allocated collection (has no fixed capacity);
thus, its add
method will not fail
because of capacity.
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.
Two CreditCard
instances are
considered duplicates if equals
returns true
.
GlobalCredit
CollectionGlobalCredit 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) is 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());
The above code fragment prints:
true 1 true 2 false 2
Collections usually provide methods to retrieve elements aggregated by the collection; the exact retrieval mechanism varies depending on the abstraction the collection is trying to provide.
Some collections associate a non-negative integer index with each element.
String
Portfolio
List
(Week 10)Portfolio
Investment get(int index)
Determine the investment in this portfolio with the given index.
Parameters:
index
- the number of the investment to get.
The index starts at zero and increments as investments are added.
Returns:
the investment whose index is passed.
Throws:
java.lang.RuntimeException
- if the index is less than
zero or not less than size()
Portfolio
Portfolio pf = new Portfolio("Small Portfolio", 3); pf.add(new Investment(new Stock("HR.A"), 1, 1.00)); pf.add(new Investment(new Stock("HR.B"), 1, 2.00)); pf.add(new Investment(new Stock("HR.C"), 1, 3.00)); Investment inv = pf.get(0); output.println(inv); inv = pf.get(1); output.println(inv); inv = pf.get(2); output.println(inv);
The above code fragment prints:
HR.A ACOMP CORP QTY=1 BV=1.0 HR.B BTECH INC. QTY=1 BV=2.0 HR.C CCOMP CORP QTY=1 BV=3.0
Notice that the order of the Investment
references
is the same as the order in which they were added to the
collection.
Portfolio
In general, you would write a loop if you need to visit
each Investment
.
for (int i = 0; i < pf.size(); i++) { Investment inv = pf.get(i); // do something with inv ... }
Because an index is used to visit each element, this loop is called an indexed traversal of the elements.
Some collections allow the client to retrieve an element by specifying a key value; the element corresponding to the key value (if any) is returned.
GlobalCredit
(uses the credit card number
as a key)Map
(Week 10)GlobalCredit
CreditCard get(String number)
Find the card whose number is passed.
Parameters:
number
- the number of the card to find.
Returns:
a reference to the card whose number is passed.
If the card is not found in the collection,
or if the passed number is null
,
then null
is returned.
GlobalCredit
GlobalCredit gc = new GlobalCredit(); gc.add(new CreditCard(111111, "John A")); CreditCard cc = gc.get("111111-3"); if (cc != null) { output.println(cc.getName()); }
The above code fragment prints:
John A
Notice that when you use key-based retrieval you have to deal with the case where no element in the collection corresponds to the key.
GlobalCredit
GlobalCredit
does not support index-based
traversal. Instead, it supports a generic type of
traversal where all that matters is that each element
is visited once.
You use a special type of for
loop
(called the enhanced for
loop, or
the for-each
loop:
GlobalCredit gc = GlobalCredit.getRandom(); for (CreditCard cc : gc) { output.println(cc.getNumber()); }
You read the loop like:
for each CreditCard cc in gc
This type of traversal is called iterator-based traversal
because an object (of type Iterator<CreditCard>
)
that is hidden by the for-each
loop is responsible
for safely traversing the collection.
Which classes support iterator-based traversal? You need to check the top of the class API:
If the class implements the Iterable
interface
then you can use a for-each
loop.
for-each
loops also work with Java arrays.