CSC72002Object Oriented Programming

FIND A SOLUTION AT Academic Writers Bay

CSC72002
Object Oriented Programming
Topic 3
Generics and Lambda Expressions
©
Southern Cross University
Developed and produced by Southern Cross University
Military Rd, EAST LISMORE. N.S.W. 2480. 2nd Session, 2018.
No part of this publication may be reproduced, stored in a retrieval system or transmitted
in any form of by means electronic, mechanical, photocopying, recording or otherwise
without the prior written permission of the publisher.
Copyright materials reproduced herein are used under the provisions of the
Copyright Amendment Act (1989).
Readings, if any, indicated in this work have been copied under section VB of the Copyright Amendment Act 1989
Copies, if any, were made by Southern Cross University in February, 2017
for private study only by students.
CAL LICENSED COPY – UNAUTHORISED COPYING PROHIBITED
CSC72002 Study Guide
3-3
Contents
GENERICS AND LAMBDA EXPRESSIONS ……………………………………………………………………………………………4
References……………………………………………………………………………………………………………………………………………..4
Objectives………………………………………………………………………………………………………………………………………………4
Introduction……………………………………………………………………………………………………………………………………………4
Generics ………………………………………………………………………………………………………………………………………………..4
A generic example ……………………………………………………………………………………………………………………………….4
Generic classes……………………………………………………………………………………………………………………………………6
Generic interfaces ……………………………………………………………………………………………………………………………….8
Generic methods………………………………………………………………………………………………………………………………..10
Bounded type…………………………………………………………………………………………………………………………………….10
Wildcard types…………………………………………………………………………………………………………………………………..11
Functional forms …………………………………………………………………………………………………………………………………..12
Lambda expressions …………………………………………………………………………………………………………………………..12
Provided interfaces ……………………………………………………………………………………………………………………………13
Summary ……………………………………………………………………………………………………………………………………………..15
Answers to Activities …………………………………………………………………………………………………………………………….16
CSC72002 Study Guide Generics and lambda expressions
3-4
Generics and Lambda Expressions
References
Liang, Y.D. 2015. Introduction to Java Programming – Comprehensive Version, 10th Edition, Pearson,
USA. ISBN:978-1-292-07001-8.
Objectives
On completion of this topic you should be able to:
1. Use generics in your programs
2. Write and use generic classes, interfaces and methods.
3. Use generics bounded type and wildcard types.
4. Recognise and interpret lambda expressions in Java programs.
5. Use lambda expressions in a Java program.
Introduction
In this topic we will introduce Generics, which are a facility available in Java since version 5 of the
language. Generics are a way to add type parameters to your function, interface and class definitions.
In this topic we will look at using generics and how you may implement you own generic function,
interface or class. In practice you will not need to implement a generic very often but an understanding
of how they work will help you understand them better when you use the many Java API generic classes
and interfaces.
In the following Topic we will look at the Java collections library. Java collection are all implemented
using generics and you will see how this makes them very useful for our programs. Collections are not
the only use of generics in the Java libraries and we will come across some more when we look at
JavaFX.
In this Topic we will also look at lambda expressions which are a different idea but which rely on a
special form of generic interface. Lambda expressions are another very useful feature of Java added in
version 8 of the language. Although you do not need to understand generics to use lambda expressions,
you will understand them better once you see the underlying generic interface that implements them.
You will come across lambda expressions or their equivalent in many modern languages, e.g. C#,
JavaScript and Typescript.
Generics
To learn Java generics, we will first introduce an example of the ArrayList generic class from the
Java collection library. We will then look at how a generic class can be implemented. Finally, we will
look at generic functions and interfaces.
A generic example
We will introduce generics with an example from the Java collections library called ArrayList. This
class is an implementation of an array, except that it has flexible length (hence the List suffix). This
means we can add and remove elements without worrying about the “array out of bounds” errors that
simple arrays can produce.
First some example of ArrayList declarations. ArrayList is defined in the java.util.* package.
The following are some declaration that could occur in your Java code:
CSC72002 Study Guide Generics and lambda expressions
3-5
ArrayList<Integer> a1;
ArrayList<Double> a2;
ArrayList<Pet> a3; // here Pet is declared in the program
Notice how we are using a new syntax of the angle brackets ‘<’ and ‘>’. These are appended to the
generic class (or interface) and contain a type parameter. This is a new idea and it will take some time
to get used to parameters being types rather than the values passed to methods that you are used to. Just
remember the angle brackets ‘<’ and ‘>’ enclose types and not expressions that result in a value.
An important restriction on generics in Java is that the type parameter cannot be a primitive type such
as int, double, etc. For example, the following declaration is illegal:
ArrayList<int> a4; // syntax error
This would produce a syntax error “Unexpected type” because the compiler expects to find a type
reference in the type parameter (not a primitive type). This is not a large problem because, as you know,
each of the primitive types has a wrapper class that can be substituted, and the compiler will
automatically convert a primitive type into an object of the wrapper type (boxing) and back again
(unboxing).
As for all non-generic classes, the above declarations only declare the reference to the actual object.
We can initialise the above three references using a new statement as follows:
ArrayList<Integer> a1 = new ArrayList();
ArrayList<Double> a2 = new ArrayList<>();
ArrayList<Pet> a3 = new ArrayList();
Did you notice the second new statement? It’s the only one with the ‘<>’ generic parameters and they
are empty. Both types of new statements can be used and there is no preferred method (to this author’s
knowledge) but you should aim to be consistent.
Now, how do we use the declared reference? This depends on the methods defined in the generic class.
In the case of ArrayList, here are some of the methods:
void add(ob)
void add(index,ob)
ob get(index)
boolean contains(ob)
int indexOf(ob)
ob remove(index)
int size()
– add an object of the type parameter
– add an object at position ‘index’
– get object of the type parameter that is at position ‘index’
– check if object ob is in ArrayList
– returns index of the object or -1
– remove object at ‘index’, returning object or null
– return number of objects in ArrayList
There are many other methods in ArrayList but these give an overview of how the collection can be
used. As an example, the following code adds two integer elements, retrieves one into a variable and
then deletes the first one:
a1.add(23);
a1.add(17);
int i = a1.get(0);
a1.remove(0); // remove first element (index 0)
Notice that there is no special syntax here and the object is accessed like any other objects with calls to
methods defined in the class. However, the compile is checking the types of the parameters. For
example, the first two statements the parameter must be an integer, which in this case uses the automatic
boxing from an int constant to an Integer wrapper class object. If we try to use an invalid type
parameter then we will get a syntax error, e.g.
a1.add(“Hello there”); // syntax error
This is one of the advantages of generics, we can check the type of arguments at compile type whereas
previously we would have to wait until the program was running to find the error.
CSC72002 Study Guide Generics and lambda expressions
3-6

Activity 3-1: Generics example ArrayList
1. Read the textbook Section 19.1-19.2 (pp 760-762). It uses the same ArrayList
example that we discussed above.
2. Implement the above example. Output the variable i on the console to check you
understand the methods.
3. Add two more values to the collection. Print out the size of the collection (the size()
method) and make sure you understand the number printed.
Note: we will look in more detail at the Java collections in the next topic.
Now, to understand how the implementation of generics work we will at defining our own generics.
Generic classes
To show how to implement a generic class we will implement our own, very simple, version of a generic
collection called MyCollection. You will see that, like all classes, underlying implementation is a set
of attributes and methods. The new part is the type formal parameter. You will recall that when we
defined a class method we use formal parameters in the method definition and inside the method these
parameters are accessed. Similarly, with generic classes when we define a formal class parameter and
inside the class definition we access the parameters.
Let’s start with the class outline of MyCollection:
public class MyCollection<T>
private final int INIT_SIZE = 20;
private Object[] data;
private int next;
MyCollection()
data = new Object[INIT_SIZE];
next=0;public boolean addElt(T elt)
if (next > data.length)
return false;
else
data[next++] = elt;
return true;This simple class has a constructor and a method to add elements to the object. Here the formal type
parameter T appears in the class header next to the class name. The same parameter then appears
throughout the definition where a type would normally appear. In this case it appears in the type for the
parameter to the addElt() method.
The above definition also demonstrates a limitation on the Java language with generic types. We cannot
use a generic type symbol in array definitions. The reason is that the original Java array is not
compatible with generic types and Java maintains backward compatibility with arrays from early
version of the language. In other languages, e.g. C#, generics also allow substitution of the formal
parameter in array definitions.
We can continue to add methods to the MyCollection class to make it more useful. For example, we
can implement a method to retrieve elements from the collection with the following getElt() method.
public T getElt(int index)
CSC72002 Study Guide Generics and lambda expressions
3-7
In this case the type parameter is used as the return type of the method. Notice how we also use the
type conversion operation ‘(T)” on the array element to convert it to the appropriate type.
We can also implement a simple function to return the number of elements in the collection as follows.
public int size()
return next;A more complicated method is to remove an element. We can implement such a method to remove the
element at the given index and also return the element as a result of the method as follows.
public T removeElt(int index)
if (index < 0
This is more complicated because to remove an element from the collection we must shuffle all the
remaining elements in the internal array to remove the gap where the removed element was located.
Now we have a generic definition we can use the class. The following call adds two elements to our
collection, prints the first one on the console, adds another element, prints the size of the collection,
removes the first element and finally prints the current first element in the collection.
MyCollection<Integer> my1 = new MyCollection();
my1.addElt(23);
my1.addElt(-10);
System.out.println(my1.getElt(0));
my1.addElt(7);
System.out.println(“size = “+my1.size());
my1.removeElt(0);
System.out.println(my1.getElt(0));
This will display the following on the console:
23
size = 3
-10
Now the above example does not do anything a non-generic class definition would have done. To see
the power of generics we can also define a String object collection with the same generic class and
perform similar operations as follows.
MyCollection<String> my2 = new MyCollection();
my2.addElt(“red”);
my2.addElt(“green”);
System.out.println(my2.getElt(0));
my2.addElt(“blue”);
System.out.println(“size = “+my2.size());
my2.removeElt(0);
System.out.println(my2.getElt(0));
This time the following will be displayed on the console:
red
size = 3
green
By using the generic class we now have the same code to implement a collection of integers, a collection
of strings, or a collection of any other type of elements.
CSC72002 Study Guide Generics and lambda expressions
3-8

Activity 3-2: Generic classes
1. Read the textbook Section 19.3 (pp 762-764). Note that this cheats a bit by using
another generic class as the data structure inside the definition. That way it avoids the
issues with using arrays and generic types mentioned above. It also uses the concept of
a stack that you may not have come across before. We will look at stacks and queues
in a following Topic so don’t be too concerned about the idea at this stage.
2. Implement the MyCollection example above and test it.
3. Add another method to dump out the data in the object. Just write it to the console
assuming that individual items can be printed with the println() function. Test it by
calling the method after the above examples.
4. (challenging) Instead of removing by index number, implement a member that
removes the object given as its argument. You will need two versions: one to remove
the first occurrence and one to remove all occurrences. Just return true or false
depending on whether something was deleted. Use the above dump method to debug
your code.
We will now look at the other generic constructs in Java.
Generic interfaces
Generic interfaces are very similar to generic classes. If you have read the textbook in the first reading
in this topic you would have seen a system generic interface called Comparable<T> which is
implemented in several Java generic classes. It is defined simply as:
public interface Comparable <T>
public int compareTo(T o);As above, T is the formal parameter for the interface and is used in the interface member definition.
The interface itself is used in various operations, for example the sort() method in the ArrayList
collection can use a class that implements this interface.
To demonstrate use of this interface we will implement a simple class that has a comparison method
that is more complicated than the simple comparisons that you are used to. Below is the start of the
definition of a class that represents pets that has two attributes. We will implement a compareTo()
method that compares both attributes.
public class Pet implements Comparable<Pet>{
private String species;
private String name;
Pet(String s, String n)
species=s;
name=n;public String getSpecies() return species;
public String getName() return name;
Now we can implement the compareTo() method for the interface as follows. Here we are comparing
the species attribute first and then, if that is the same, we compare the name attribute. This makes
use of the Comparable<String> implementation of the String class.
CSC72002 Study Guide Generics and lambda expressions
3-9
public int compareTo(Pet p)
if (p==null)
throw new NullPointerException();
else
if (p.getSpecies().equals(species))
return name.compareTo(p.getName());
else
// same species
// compare names
return species.compareTo(p.getSpecies());// compare speciesNow to use this class we can create a new ArrayList object with some pets, e.g.
ArrayList<Pet> pets = new ArrayList();
pets.add(new Pet(“dog”, “Terry”));
pets.add(new Pet(“dog”, “Missy”));
pets.add(new Pet(“cat”, “Spike”));
pets.add(new Pet(“fish”, “Wanda”));
pets.add(new Pet(“cat”, “Panda”));
We can then sort the pets in the collection using the implementation of the Comparable<Pet> interface
in the Pet class. This is achieved by calling the sort() method:
pets.sort(null);
The null parameter is used to force the sort() method to use the object compareTo() method. We will
see in a following section how lambda expressions can be used to sort using whatever comparison we
wish. To print out the sorted data we can use a for-each loop:
System.out.println(“After sort”);
for (Pet p: pets)
System.out.println(” “+p);Which will display the following on the console (note the new order):
After sort
cat named Panda
cat named Spike
dog named Missy
dog named Terry
fish named Wanda
This formatted data is a result of a toString() method being defined in the Pet class as follows.
@Override
public String toString()
return “” + species + ” named ” + name;The following activity asks you to implement the above code. Note that there is a lot of code to test the
small generic interface but this coding pattern occurs quite frequently when you use the Java APIs.

Activity 3-3: Generic interfaces
1. Implement the above Pet class with the implementation of the Comparable<Pet>
interface. In your code print out the contents of the collection before the sort operation
so you can compare the contents after the sort() call.
2. Modify the compareTo() method from 1. To use a different comparison operation.
For example, you could implement a comparison that just uses the name attribute
(ignore the species attribute).
We will now look at the other generic objects in Java, the generic methods.
CSC72002 Study Guide Generics and lambda expressions
3-10
Generic methods
Generic methods are another type of generic definition available in Java. It’s the same idea but applied
to individual methods. The syntax is slightly different however. A generic method is a static method
with a type parameter.
As an example of a generic method, consider the following method that prints the contents of any array.
public static <T> void printArray(T[] array)
for (T elt: array)
System.out.println(elt);Now to use this method we can pass any type of array as a parameter. Consider the following two array
definitions (Pet is defined in the previous section).
Integer[] intArray = 3, 10, -5, 0, 10;
Pet [] morePets =
new Pet(“snake”, “Slim”),
new Pet(“feret”, “Freda”),
new Pet(“rock”, “Sleepy”)
;
We can use the generic method to print the contents of these arrays as follows.
printArray(intArray);
printArray(morePets);
Notice how we do not have to specify the type. The compiler automatically determined the type of the
argument in this example. In the rare cases where the compiler cannot deduce the type we can specify
the correct type. For example, in the above two calls we could have specified the type as follow.
MyClass.<Integer>printArray(intArray);
MyClass.<Pet>printArray(morePets);
This is a little different than what you would expect. We need to put the class name (MyClass) before
the method, which is not unusual for static methods. Also, the type parameter is placed before the
method identifier when usually we put parameters after the identifier. Obviously, when possible we
allow the compiler to automatically fill in the details when it can and only use the long syntax when we
have to.

Activity 3-4: Generic methods
1. Read the textbook section 19.4 (pp 764-766). We will look at the bounded types in the
next section.
2. Implement the above generic method and test it with the two arrays shown.
3. Add another Double array with some data and test it as well.
Another attribute of generics is bounded types that we will look at next.
Bounded type
Sometimes we wish to restrict the types that can be used as parameters to a class, interface or method.
Up to this point we have allowed given type parameters to be any class at all. We restrict the type given
as argument by using the inheritance structure of classes and interfaces. This is achieved by specifying
a base class for the type parameter in question. You will probably not use this in your programming
very often but the Java APIs use this frequently.
As an example of a bounded type consider the following definition of a member function that can return
the maximum of two objects with the same or derived type.
CSC72002 Study Guide Generics and lambda expressions
3-11
public static <T extends Comparable<T> > T maximum(T arg1, T arg2)
if (arg1.compareTo(arg2) < 0)
return arg2;
else
return arg1;This generic method has a type parameter which must be derived from the Comparable interface that
we looked at above. The reason this is required is that a call to the compareTo() method that the
interface enforces is made in the member definition. So, the bounded type is making use of the basic
Java interface implementation.
Now remember that we implemented the interface in the Pet class above. That means we can display
on the console the maximum of any two pets, e.g.
Pet p1 = new Pet(“dog”, “Missy”);
Pet p2 = new Pet(“dog”, “Terry”);
System.out.println(maximum(p1, p2));
This will display the following.
dog named Terry
So here the compiler has deduced that the type for the generic maximum() method is Pet and this
implements the Comparable<Pet> interface. If we tried to call maximum() with objects that do not
implement the Comparable<T> interface then a syntax error will occur because of the type bounds.

Activity 3-5: Bounded types
1. Implement the above maximum() method and test it with the two Pet objects.
2. Test the maximum() method with two Integer objects. Why does that work?
3. Why can’t we use a Integer and a Pet argument to the maximum function. If you
can’t answer that try it and read the syntax error.
The final attribute of generics is wildcard types that we will look at next.
Wildcard types
Wildcard types are a tricky idea but essential for many generic type definitions. The general idea is that
a wildcard is required when we use objects generated by generic classes with related but not identical
type parameters. For example, the two classes:
Arraylist<Number>
ArrayList<Integer>
are related because Integer is a subclass of Number. As you know, this means an Integer object
has inherited the methods from the Number class so we can use polymorphism in our code to process
both types of objects using the common methods. However, with generics this can pose a problem. As
an example, consider the following method header for adding numbers in an ArrayList<Number>
which should be able to process Integer, Double and other subclasses of Number.
public static double sumAR(ArrayList<Number> ar)
double sum = 0.0;
for (int i =0; i<ar.size(); i++)
sum = sum + ar.get(i).doubleValue();return sum;The wildcard will only apply to the method header. In this definition we have used a call to
doubleValue() which is a method in the Number class so is defined in all subclasses.
Now the following will cause a syntax error even though Integer is a subclass of Number:
CSC72002 Study Guide Generics and lambda expressions
3-12
ArrayList<Integer> ilist = new ArrayList();
ilist.add(23);
ilist.add(-2);
ilist.add(100);
// the following will cause a syntax error
System.out.println(“integer list sum = ” + sumAR(ilist));
The problem is that the generic parameter ArrayList<Number> does not match the actual parameter
ArrayList<Integer> because the generic system generates a different class for each instance of the
generic and the generated classes are not compatible. However, wildcards can be used to notify Java at
subclasses can be used in the parameter to the generic. The following definition says that the generic
ArrayList parameter can have a Number type argument or any derived type.
public static double sumAR(ArrayList<? extends Number> ar) {
So, in general, wildcards are necessary when we want type parameters that can cope with types that are
subclasses of some type. There are also cases when we want to define generics where the type parameter
can be superclasses of some class. There is an example in the reading below but we will not come
across this often.
In Java there are three possible syntax for wildcards:
<?>
<? extends T>
<? super T>
The first is shorthand for <? extends Object>. This means that any object class can be used as a
type parameter because, as you have learned, all classes have Object at the root of their inheritance
hierarchy. The second syntax we saw in the example above and the third you will see in the reading.

Activity 3-6: Wildcards generic types
1. Read section 19.7 (pp 769-771). Closely read the super type example and try to think
of where this would be useful (not very often).
2. Test the sumAR() method defined above. Try calling it with a ArrayList<Double>
array to see it will work with another subclass of Number.
Next, we look at lambda expressions
Functional forms
Functional forms (sometimes called “lambdas” or “lambda expression”) were introduced into Java
version 8. The idea originated in the 1950s and 1960s is the lambda calculus and the LISP language
which is based on the lambda calculus. Functional forms are now included in other languages such as
Java and C#.
A functional form in Java is technically a functional interface. Its semantics are tied to an interface with
a single abstract method (SAM). However, the Java language now also provides syntax for
automatically connecting to the underlying interface, these are called lambda expressions. We will look
at the simple lambda expression first before looking at the technical implementation details.
We will also be using many functional forms in later topics. Lambda expressions are used extensively
for event handlers in JavaFX and for processing collections in the Java collection library.
Lambda expressions
A lambda expression is the syntax of a functional form for Java programming. One way to think of
lambda expressions is a function without a name. A lambda expression lists the formal parameters and
result of the function. The syntax is somewhat flexible and we will demonstrate by example.
Suppose we want a function that takes a string as parameter and returns its length. A lambda expression
for this function can be written is several ways:
CSC72002 Study Guide Generics and lambda expressions
3-13
s -> s.length()
(s) -> s.length());
s -> int l = s.length();
return l;
The first and second lambda expression are equivalent except for the parentheses around the parameter.
The third example defines a function body with a temporary variable and two statements to compute
the answer.
To fully type the lambda expressions, we can add type information so the compiler will check that the
correct types are used. For example, the above function can be written:
(String s) -> s.length()
We are not restricted to one parameter. For example, the following lambda expressions define a function
to add two numbers together (un-typed and typed version):
(x,y) -> x+y
(int x, int y) -> x+y
We can also have no parameters, e.g.
() -> “error”
This example returns a string without requiring any parameters.

Activity 3-7: Lambda Expressions
Lambda expressions are shown in the textbook in the JavaFX section (Section 15.6, pp 597-
599). Unfortunately, this is heavily related to JavaFX event handling which we will look at in a
following Topic. Nevertheless, it is worth having a look at this now.
1. Write down a lambda expression that takes two strings and returns the concatenation of
the two strings.
2. Write down a lambda expression that takes a string as an argument and writes it on the
console (System.out).
Note: although you can code these expressions, we have not seen how they fit in a program so
you will not be able to test them in the NetBeans IDE yet. You may like to come back after the
next section.
Now, the above examples show how to write a standalone lambda expression but they do not show how
to use one. It turns out that using such a function is a bit trickier. Luckily, most use of lambda
expressions is as arguments to methods in Java supplied APIs but we will look at using them in your
own code so you have a better idea of how they work. We will demonstrate their use in several later
topics.
Provided interfaces
As mentioned above, a lambda expression is a functional form that maps to an interface with one abstract
member function. Java provides a long list of interfaces that cover most of the lambda function that we
wish to use. These are in the package:
java.util.function.*
The idea is to reuse the interfaces in these packages instead of writing our own interfaces. You may
need to write your own interfaces in future but you will see the standard interfaces will cover most uses
that arise in this unit. To apply lambada expressions we need to implement the corresponding interface.
A general-purpose interface for functions with one argument and a result is the Function<T,R>
interface. This interface like all the interfaces in java.util.function are defined as generic
interfaces so we can insert own types. As explained above this interface has one abstract member so a
lambda expression can be applied. In this case it is the apply(T t) member that takes a type T
argument and returns a type R result.
CSC72002 Study Guide Generics and lambda expressions
3-14
To see how we can use Function<T,R>, we can assign a lambda expression to a variable as follows:
Function<String, Integer> func = s -> s.length();
Now, we cannot apply the new variable as a function directly. Remember that Function is an interface
with an abstract method apply() which must be called. So, if we wanted to apply this function to say
the string “Hello” and display the result we could code:
System.out.println(“length: “+func.apply(“Hello”));
There are many more interfaces defined in the java.util.function package. Some of them are:
BiFunction<T, U, R> – a function with two arguments (types T and U) and result of type R.
BinaryOperator<T> – a function of two arguments and return result all of type T
Consumer<T> – a void function with parameter of type T
Producer<T> – a function with no arguments but returns type T
Predicate<T> – a Boolean function with single argument of type T
UnaryOperator<T> – a function with argument and returned result of type T.
You may have noticed we were required use to the Integer wrapper class in the example declaration
above instead of the primitive type int. We mentioned this when discussing generics definitions, that
is we needed to have a class type parameter rather than a primitive type. To avoid us having to program
the conversion between the primitive types and the wrapper classes the java.util.function
package also has definitions to avoid the wrapper class but provide the same service. For example, the
above code could have been written.
ToIntFunction<String> func2 = (String s) -> s.length();
System.out.println(“length: “+func2.applyAsInt(“Hello”));
Here the apply() function in the Function<X,R> interface has been replaced with the
applyAsInt() function in this interface.
Similarly, there are set of interfaces to be used for function with int arguments. The corresponding
function that takes a single int argument and returns a type R is the IntFunction<R> interface.
All the primitive types: int, long and double have corresponding interfaces and combinations of
primitive arguments and primitive results have interfaces as well, e.g.
LongFunction<R> have – single long argument with result type R
DoubleToIntFunction – double argument and int result
While the above code demonstrates the use of lambda expressions when assigned to variables it has not
shown examples that you would immediately see as useful. The lambda expressions become very useful
when they are used as arguments to methods. This is how JavaFX and the Generic collections use them
to allow concise smaller code to be used. When we call these member functions we can use lambda
expressions as arguments.
To demonstrate we will use the ArrayList<T> generic class as we have throughout this topic.
ArrayList<T> has a member function with the following signature:
forEach(Consumer<? super T>)
Now Consumer is a function interface (as mentioned above) that represents a void function with a
superclass of T as its argument. The idea is that we apply the function to each of the elements in the
ArrayList collection. Since the function is void we do not have to worry a returning a result for each
application.
As an example of using this function look at the following example call. It shows a lambda expression
that returns no value but calls a standard method to display each of the elements on the console.
CSC72002 Study Guide Generics and lambda expressions
3-15
ArrayList<Integer> ilist = new ArrayList();
// … add some elements
ilist.forEach(
i -> System.out.println(” “+i);
);
This will print each integer element on the console with three spaces before the value.
Another useful member function in ArrayList<T> has the following signature:
replaceAll(UnaryOperator<T> operator)
This member uses the UnaryOperator<T> functional form mentioned above, which takes a single
parameter of type T and return an object of type T. The method takes each of the elements in the
ArrayList object and replaces them with the result of applying the function to the current element.
As an example, we can add 1 to each of the elements in the above ArrayList<Integer> collection
with the following code:
ilist.replaceAll(i -> i+1);
Both the forEach() and replaceAll() member functions are available in most of the Java
collections as we will see in the following Topic.

Activity 3-8: Lambda Expressions as parameters
1. Implement the above ArrayList<Integer> and add some elements as we did in
previous sections of this Topic. Then print out the values using the forEach()
method with a lambda expression as show above.
2. Use the replacesAll() method as shown above to add 1 to each of the elements in
the ArrayList<Integer> object. To check it works you will need to print out all the
elements a second time.
3. Square each of the elements in the ArrayList<Integer> object (multiply each by
itself). Print out all the elements again to check that it works.
That’s enough for this Topic. Lambda expressions will come up in several of the following Topics.
Summary
In this Topic we have looked two different aspects that appear in modern object-oriented programming
languages. We looked at generics, which is the ability to specify type parameters to our class, interface
and method definitions to save us the effort of repeating code with different types. The Java API libraries
use generics extensively in their implementation so you will be using them quite a bit in future topics.
However, in practice you will not need to define your own generic definitions very often but
understanding how they work is very important and will help you use the Java API more effectively.
The second aspect of object-oriented languages was functional forms and lambda expressions. A lambda
expression is a way of defining unnamed function. In Java it is applied by implementing an interface
with a single abstract method. You will have seen that Java supplied a large collection of interfaces that
will allow use of most lambda expressions that we will require. We will come across lambda
expressions as parameters to API member functions is several of the following Topics.
CSC72002 Study Guide Generics and lambda expressions
3-16
Answers to Activities
Nearly all of the activities in this study guide involve programming exercises so we will not provide
answers here. The activities below asked some questions so we have provided some answers.
Activity 3-:
The.

READ ALSO...   flexible budget as compared to a forecast budget
Order from Academic Writers Bay
Best Custom Essay Writing Services

QUALITY: 100% ORIGINAL PAPERNO PLAGIARISM – CUSTOM PAPER