In Python you covered lists. We saw that a list was a variable which could be used to hold more than one item, and could be extended to hold new data.
In Java, the ArrayList provides similar functionality to the Python list. We can create an ArrayList and then keep adding objects to it until
the JVM's memory runs out. This makes the ArrayList much more flexible than a plain array.
Here is an example of code which uses an ArrayList. Imagine we have a Product
class:
// Product class public class Product { private String name; private double price; private int quantityInStock; public Product (String nameIn, double priceIn, int quantityIn) { name = nameIn; price = priceIn; quantityInStock = quantityIn; } public String toString() { return "Name=" + name + " Price=" + price + " Quantity in stock=" + quantityInStock; } }we could then create an
ArrayList
of Product
s as follows:
// Main class import java.util.ArrayList; public class ArrayListApp { public static void main (String[] args) { ArrayList<Product> products = new ArrayList<Product> (); Product product1 = new Product("Smartphone", 299.99, 5); Product product2 = new Product("Tablet", 199.99, 3); Product product3 = new Product("SD Card", 9.99, 100); products.add(product1); products.add(product2); products.add(product3); for(int count=0; count<products.size(); count++) { Product currentProduct = products.get(count); System.out.println(currentProduct); } } }
import
the ArrayList from java.util
before we use it:
import java.util.ArrayList;
main()
creates the ArrayList:
ArrayList<Product> products = new ArrayList<Product> ();Note that ArrayLists are objects, so we use new to create them, just like any other object. Note that the data type includes what type of data the ArrayList is holding, so here the data type is ArrayList<Product> because it is an ArrayList holding Product objects. This is a Java feature known as generics: ArrayList is a generic type, i.e. it can hold objects of any specified data type, and we need to specify which type we want it to hold.
ArrayList<Product>
by contrast is a specific type of ArrayList
that can hold only Product
s.
add()
method of
ArrayList.Product currentProduct = products.get(count);This line is creating a variable called currentProduct and setting it equal to the current member of the ArrayList.
The code above was written in a way to try and make it as clear as possible what is going on. However, we could write the code more efficiently (less lines of code) as follows:
import java.util.ArrayList; public class ArrayListExample1 { public static void main (String[] args) { ArrayList<Product> products = new ArrayList<Product> (); products.add(new Product("Smartphone", 299.99, 5)); products.add(new Product("Tablet", 199.99, 3)); products.add(new Product("SD Card", 9.99, 100)); for(int count=0; count<products.size(); count++) { System.out.println(products.get(count)); } } }Note how, rather than creating three variables
product1
, product2
and product3
, we create the product objects and add them to the array list in one statement. This is perfectly acceptable as the add()
method of the ArrayList is expecting a Product
object as a parameter - and we are giving it one.
Note also how we combine two statements into one in the for loop. Rather than storing the current member of the ArrayList in a variable called currentProduct
and then print it directly using the return value of products.get(count)
. Since products.get(count)
gives us a Product object, this is, again, acceptable.
So far we have considered single objects, or objects within arrays or ArrayLists. However, real object-oriented systems typically have many objects interacting with one another. A common scenario is to have objects within other objects and this is called aggregation.
Imagine we wanted to write a program to manage stock for a shop. We could write a main() which creates an ArrayList of Product objects (as in the example above) and implement functionality within the main() to search for products, sells products, adds new products and so on. However a more object-oriented approach would be to create a class which represents the shop as a whole. This class could be called Shop. It could contain methods to add a new product, search for a product, or sell a product, and could contain, within it, an ArrayList of Product objects (this would be the aggregation). The advantage of creating a Shop class is that it could be reusable: we could create a Shop class which represents a shop, and then reuse it in many different programs. Also it allows another level of encapsulation: the outside world can use the Shop
via its method, without knowing its inner workings.
This example shows the use of a Shop class, as well as a Product class and a test main()
.
// Product class public class Product { private String name; private double price; private int quantityInStock; public Product (String nameIn, double priceIn, int quantityIn) { name = nameIn; price = priceIn; quantityInStock = quantityIn; } public String toString() { return "Name=" + name + " Price=" + price + " Quantity in stock=" + quantityInStock; } public boolean sell() { if(quantityInStock > 0) { quantityInStock--; return true; } else { return false; } } public String getName() { return name; } }
// Shop class import java.util.ArrayList; public class Shop { private String name; private ArrayList<Product> products; public Shop(String nameIn) { name = nameIn; products = new ArrayList<Product> (); } public void addProduct (Product p) { products.add(p); } // Search for a product by name public Product searchForProduct (String searchName) { for(int count=0; count < products.size(); count++) { Product currentProduct = products.get(count); if(currentProduct.getName().equals(searchName)) { return currentProduct; } } return null; } public boolean sellProduct (String productName) { Product p = this.searchForProduct (productName); if (p != null) { return p.sell(); } else { return false; } } }
// Test main public class ShopTestApp { public static void main (String[] args) { Shop shop = new Shop("Cottage Stores"); shop.addProduct (new Product ("Cheese", 1.99, 10)); shop.addProduct (new Product("Milk", 0.50, 20)); shop.addProduct (new Product("Bread", 1.19, 15)); boolean cheeseSellStatus = shop.sellProduct("Cheese"); System.out.println(cheeseSellStatus ? "Cheese sold" : "Cheese could not be sold"); boolean spamSellStatus = shop.sellProduct("Spam"); System.out.println(spamSellStatus ? "Spam sold" : "Spam could not be sold"); } }How is this working?
searchForProduct()
will return
null
if the product cannot be found.
Note the use of .equals() to compare strings in searchForProduct(). When comparing strings,
we do not use ==
. We instead, use the .equals() method of the String class, passing in the
string to compare to as a parameter.sellProduct()
method contains error checking: it will attempt to sell a given product and if it
cannot be found, it will display an error. It calls searchForProduct()
to try
and find the product with that name. If it can be found, a Product object is returned, and
the product is sold by calling its sell()
method. If it cannot be found,
null is returned and we display an error.You'll also notice in the above code that sell()
and sellProduct()
do not use a System.out.println
to inform the user of success or otherwise. Instead, they return a boolean. This boolean status code is then used in the main()
to print an appropriate message.
Why is this done? It's the same reason we used toString()
last week. It increases the reusability of our code, in that it can now be used in non-console applications such as web applications or Android apps, where System.out.println()
cannot be used. The equivalent of main()
in these apps could test the boolean return code and display an appropriate message in an appropriate format. Also it means that different console-mode applications which use our code can display their own message rather than a hard-coded message within Product
or Shop
.
Also note this code in the main()
:
boolean cheeseSellStatus = shop.sellProduct("Cheese"); System.out.println(cheeseSellStatus ? "Cheese sold" : "Cheese could not be sold");What is this? It is a concise version of an
if
statement using the ternary operator (?). It means: if cheeseSellStatus
is true
, print "Cheese sold", otherwise, print "Cheese could not be sold".
Student
example from previous weeks. In your main()
, create a ArrayList
of students, and in the loop, add each Student
objects to the ArrayList
as soon as you create it. Then, when all students have been entered, write a second loop to loop through the array list and display each student in turn.AggregationApp
), and add your Student
class to it, as well as a main class. Rather like the Shop
in the example, create a University
class. The University
should contain, as an attribute, an ArrayList
of Student
s. The University
should include these methods:
enrolStudent()
- this should add a new student to the university by adding it to the array list.findStudentById()
- this should find a single student by student ID. If no student with that ID can be found, it should return null
.findStudentsByName()
- this should find all students that have a particular name. It should return an ArrayList
of all matching students. To do this, you will need to declare an ArrayList
in the method, loop through all students, and add any students with that name to the ArrayList
before returning it at the end.main()
, create a University
object. Then, develop a simple menu-driven application to add and search for students. The menu should look like this:
1. Add a student 2. Search for student by ID 3. Search for students by name 4. QuitYou will need a
String
variable to read in the user's menu choice. Add a while
loop which keeps looping until this variable has the value "4". Inside the loop, test which option the user entered, and either:
Student
object and adding it to the University
),