Arraylist Class and Generic Types
Introduction:
At its core, the term generics means parameterized types. Parameterized types are important because they enable you to create classes, interfaces, and methods in which the type of data upon which they operate is specified as a parameter. Using generics, it is possible to create a single class; that automatically works with different types of data.
A class, interface, or method that operates on a parameterized type is called generic, as in generic class or generic method. It is important to understand that Java has always given you the ability to create generalized classes, interfaces, and methods by operating through references of type Object. Because Object is the super class of all other classes, an Object reference can refer to any type object. Thus, in pre-generics code, generalized classes, interfaces, and methods used Object references to operate on various types of objects. The problem was that they could not do so with type safety.
Generics add the type safety that was lacking. They also streamline the process, because it is no longer necessary to explicitly employ casts to translate between Object and the type of data that is actually being operated upon. With generics, all casts are automatic and implicit. Thus, generics expand your ability to reuse code and let you do so safely and easily.
Non-Generic Box Class:
Begin by examining a non-generic Box class that operates on objects of any type. It needs only to provide two methods: set, which adds an object to the box, and get, which retrieves it:
public class Box { private Object object;
public void set(Object object) { this.object = object; } public Object get() { return object; }
}
Since its methods accept or return an Object, you are free to pass in whatever you want, provided that it is not one of the primitive types. There is no way to verify, at compile time, how the class is used. One part of the code may place an Integer in the box and expect to get Integers out of it, while another part of the code may mistakenly pass in a String, resulting in a runtime error.
A Generic Version of the Box Class:
A generic class is defined with the following format:
class name<T1, T2, Tn> { /* … */ }
The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, …, and Tn.
To update the Box class to use generics, you create a generic type declaration by changing the code “public class Box” to “public class Box<T>”. This introduces the type variable, T, that can be used anywhere inside the class.
With this change, the Box class becomes:
/**
- Generic version of the Box class.
- @param<T> the type of the value being boxed
*/
public class Box<T> {
// T stands for “Type” private T t;
public void set(T t) { this.t = t; } public T get() { return t; }
}
As you can see, all occurrences of Object are replaced by T. A type variable can be any non- primitive type you specify: any class type, any interface type, any array type, or even another type variable.
This same technique can be applied to create generic interfaces.
Type Parameter Naming Conventions:
By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the variable naming conventions that you already know about, and with good reason: Without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name.
The most commonly used type parameter names are:
E – Element (used extensively by the Java Collections Framework) K – Key
N – Number T – Type
V – Value
S,U,V etc. – 2nd, 3rd, 4th types
Invoking and Instantiating a Generic Type:
To reference the generic Box class from within your code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer:
Box <Integer> integerBox;
You can think of a generic type invocation as being similar to an ordinary method invocation, but instead of passing an argument to a method, you are passing a type argument — Integer in this case — to the Box class itself.
Like any other variable declaration, this code does not actually create a new Box object. It simply declares that integerBox will hold a reference to a “Box of Integer”, which is how Box<Integer> is read.
An invocation of a generic type is generally known as a parameterized type.
To instantiate this class, use the new keyword, as usual, but place <Integer> between the class name and the parenthesis:
Box <Integer> integerBox = new Box <Integer> ();
Diamond Operator:
In Java SE 7 and later, you can replace the type arguments required to invoke the constructor of a generic class with an empty set of type arguments (<> – referred as diamond operator) as long as the compiler can determine, or infer, the type arguments from the context. This pair of angle brackets, <>, is informally called the diamond. For example, you can create an instance of Box<Integer> with the following statement:
Box <Integer> integerBox = new Box <> ();
Java Arraylist:
The Java ArrayList is a dynamic array-like data structure that can grow or shrink in size during the execution of a program as elements are added/deleted. An Array on the other hand, has a fixed size: once we declared it to be a particular size, that size cannot be changed. To use an ArrayList, you first have to import the class:
import java.util.ArrayList;
You can then create a new ArrayList object:
ArrayListlistTest = new ArrayList( );
The Java API has a list of all the methods provided by an ArrayList.
Lab Activities:
Activity 1:
The following program shows a simple use of ArrayList. An array list is created, and then objects of type String are added to it. The list is then displayed. Some of the elements are removed and the list is displayed again.
Solution:
importjava.util.*; classArrayListDemo {
public static void main(String args[]) {
// create an array list
ArrayList al = new ArrayList(); System.out.println(“Initial size of al: ” + al.size());
// add elements to the array list al.add(“C”);
al.add(“A”);
al.add(“E”);
al.add(“B”);
al.add(“D”);
al.add(“F”);
al.add(1, “A2”);
System.out.println(“Size of al after additions: ” + al.size());
// display the array list System.out.println(“Contents of al: ” + al);
// Remove elements from the array list al.remove(“F”);
al.remove(2);
System.out.println(“Size of al after deletions: ” + al.size());
System.out.println(“Contents of al: ” + al);
}
}
The output from this program is shown here:
Initial size of al: 0
Size of al after additions: 7
Contents of al: [C, A2, A, E, B, D, F] Size of al after deletions: 5
Contents of al: [C, A2, E, B, D]
Activity 2:
The following program defines two classes. The first is the generic class Gen, and the second is GenDemo, which uses Gen.
Solution:
// A simple generic class.
// Here, T is a type parameter that
// will be replaced by a real type
// when an object of type Gen is created.
class Gen<T> {
}
T ob; // declare an object of type T
// Pass the constructor a reference to
// an object of type T. Gen(T o) {
ob = o;
}
// Return ob.
T getob()
{ returnob;
}
// Show type of T. voidshowType() {
System.out.println(“Type of T is ” + ob.getClass().getName());}
}
// Demonstrate the generic class. classGenDemo {
public static void main(String args[]) {
// Create a Gen reference for Integers. Gen<Integer>iOb;
// Create a Gen<Integer> object and assign its
// reference to iOb. Notice the use of autoboxing
// to encapsulate the value 88 within an Integer object. iOb = new Gen<Integer>(88);
// Show the type of data used by iOb. iOb.showType();
// Get the value in iOb. Notice that
// no cast is needed. int v = iOb.getob();
System.out.println(“value: ” + v); System.out.println();
// Create a Gen object for Strings.
Gen<String>strOb = new Gen<String>(“Generics Test”);
// Show the type of data used by strOb. strOb.showType();
// Get the value of strOb. Again, notice
// that no cast is needed.
String str = strOb.getob();
System.out.println(“value: ” + str);}
}
The output produced by the program is shown here:
Type of T is java.lang.Integer value: 88
Type of T is java.lang.String value: Generics Test
Activity 3:
You can declare more than one type parameter in a generic type. To specify two or more type parameters, simply use a comma-separated list. For example, the following TwoGenclass is a variation of the Gen class that has two type parameters:
// A simple generic class with two type
// parameters: T and V. classTwoGen<T, V> { T ob1;
V ob2;
// Pass the constructor a reference to
// an object of type T and an object of type V.
TwoGen(T o1, V o2) { ob1 = o1;
ob2 = o2;}
// Show types of T and V. voidshowTypes() { System.out.println(“Type of T is ” + ob1.getClass().getName()); System.out.println(“Type of V is ” + ob2.getClass().getName());}
T getob1() { return ob1;
}
V getob2() { return ob2;
// Demonstrate TwoGen. classSimpGen {
public static void main(String args[]) {
}
}
TwoGen<Integer, String>tgObj = newTwoGen<Integer, String>(88, “Generics”);
// Show the types. tgObj.showTypes();
// Obtain and show values. int v = tgObj.getob1();
System.out.println(“value: ” + v); String str = tgObj.getob2(); System.out.println(“value: ” + str);
}
}
The output from this program is shown here:
Type of T is java.lang.Integer Type of V is java.lang.String value: 88
value: Generics
Home Activities:
Activity 1:
Write a program that uses an ArrayList of parameter type Contact to store a database of contacts. The Contact class should store the contact’s first and last name, phone number, and email address. Add appropriate accessor and nutator methods. Your database program
should present a menu that allows the user to add a contact, display all contacts, search for a specific contact and display it, or search for a specific contact and give the user the option to delete it. The searches should find any contact where any instance variable contains a target search string. For example, if ―Elmore‖ is the search target, then any contact where the first name, last name, phone number, or email address contains ―Elmore‖ should be returned for display or deletion. Use the ―for-each‖ loop to iterate through the ArrayList .
Activity 2:
Write a generic class, MyMathClass , with a type parameter T where T is a numeric object type (e.g., Integer, Double, or any class that extends java.lang.Number ). Add a method named standardDeviation that takes an ArrayList of type T and returns as a double the standard deviation of the values in the ArrayList . Use the doubleValue () method in the Number class to retrieve the value of each number as a double. Refer to Programming Project 6.5 for a definition of computing the standard deviation. Test your method with suitable data. Your program should generate a compile-time error if your standard deviation method is invoked on an ArrayList that is defined for nonnumeric elements (e.g., Strings ).
Lab Assignment and Viva voce
Task 1:
Create a generic class with a type parameter that simulates drawing an item at random out of a box. This class could be used for simulating a random drawing. For example, the box might contain Strings representing names written on a slip of paper, or the box might contain Integers representing a random drawing for a lottery based on numeric lottery picks.
Create an add method that allows the user of the class to add an object of the specified type along with an is Empty method that determines whether or not the box is empty. Finally, your class should have a draw Item method that randomly selects an object from the box and returns it. If the user attempts to drawn an item out of an empty box, return null . Write a main method that tests your class.
Task 2:
In the sport of diving, seven judges award a score between 0 and 10, where each score may be a floating-point value. The highest and lowest scores are thrown out and the remaining scores are added together. The sum is then multiplied by the degree of difficulty for that dive. The degree of difficulty ranges from 1.2 to 3.8 points. The total is then multiplied by 0.6 to determine the diver’s score.
Write a computer program that inputs a degree of difficulty and seven judges’ scores and outputs the overall score for that dive. The program should use an ArrayList of type Double to store the scores.