Ajava Unit 1
Ajava Unit 1
1
1.1 Introduction to Generics
The Java Generics was added to JDK 1.5 which allowed programming
generically. It allows creating classes and methods that work in the same way on
different types of objects while providing type-safety right at the compile-time It
makes the code stable by detecting the bugs at compile time.
Before generics, we can store any type of objects in the collection, i.e., non-
generic.
Now generics force the java programmer to store a specific type of objects.
1.1.1 ADVANTAGE OF GENERICS
There are mainly 3 advantages of generics. They are as follows:
1) Type-safety
Example:
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);
2
AJAVA-Unit 1: Collection and Generics
3) Compile-Time Checking: Type checking is done at compile time so errors
will not occur at runtime.
Example:
List<String> list = new ArrayList<String>();
list.add("hello");
list.add(32);//Compile Time Error
1.1.2 GENERIC CLASSES
Generics is not only limited to collection. It is also possible to use Generics with
classes. A generic class declaration looks like a non-generic class declaration,
except that the class name is followed by a type parameter section.
The type parameter section of a generic class can have one or more type parameters
separated by commas. These classes are known as parameterized classes or
parameterized types because they accept one or more parameters.
Example: Program that demonstrates Generic Classes
public class Shape<T>
{ private T t; public
void add(T t) {
this.t = t;
} public T
get() { return
t;
}
public static void main(String[] args) {
Shape<Integer> intShape = new Shape<Integer>();
Shape<String> strShape = new Box<String>();
intShape.add(new Integer(25));
strShape.add(new String("Generic Classes"));
System.out.printf("Integer Value :%d\n\n", intShape.get());
System.out.printf("String Value :%s\n", strShape.get());
}
}
Output
Integer Value :25
String Value : Generic Classes
3
In this program, Box is coded as a Generic Class. Technically, Box is a parametric
class and T is the type parameter. T serves as a placeholder for holding any type of
Object. We can use the above class by substituting any kind of object for the
placeholder T.
1.1.3 GENERIC METHODS
A generic method declaration can have arguments of different types. Based on the
types of the arguments passed to the generic method, the compiler handles each
method call appropriately. Unlike a Generic Class, a generic method containing
different parameters affects only that method. alone. Hence, a class which is not
generic can contain generic and non-generic methods.
Rules for defining Generic Methods
• All generic method declarations have a type parameter section delimited by
angle brackets (< and >) that precedes the method's return type < T >
• Each type parameter section contains one or more type parameters
separated by commas. A type parameter is an identifier that specifies a
generic type name.
• The type parameters can be used to declare the return type and act as
placeholders for the types of the arguments passed to the generic method,
which are known as actual type arguments.
• A generic method's body is declared like that of any other method.
• Note that type parameters can represent only reference types, not primitive
types (like int, double and char).
Example 1: Program that prints the type of data passed using a single Generic
method
public class GenericMethodsEx1 {
// generic method print
public static <T> void print(T t)
{ System.out.println(t.getClass().getName());
}
public static void main(String args[]) {
GenericMethodsEx1.print(“Hello World”);
GenericMethodsEx1.print(100);
}
}
Output;
java.lang.String java.lang.Integer
4
AJAVA-Unit 1: Collection and Generics
In this program, the static method print has a return type void and it takes a single
parameter called T. T stands for parametric type which can be substituted with any
of the Java types by a client application.
Example 2: Program that prints an array of different type using a single
Generic method
public class GenericMethodEx2 {
// generic method printArray
public static < T > void printArray( E[] i )
{
// Display array elements
for(T element : i) {
System.out.printf("%s ", element);
}
System.out.println();
}
public static void main(String args[]) {
// Create arrays of Integer, Double and Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println("Array integerArray contains:");
printArray(intArray); // pass an Integer array
System.out.println("\nArray doubleArray contains:");
printArray(doubleArray); // pass a Double array
System.out.println("\nArray characterArray contains:");
printArray(charArray); // pass a Character array
}
}
Output
Array integerArray contains:
12345
Array doubleArray contains:
1.1 2.2 3.3 4.4
Array characterArray contains:
5
H EL L O
In this program, the static method printArray has a return type void and it takes a
single parameter called T. T stands for parametric type which can be substituted
with any of the Java types by a client application. The main method passes arrays
with different types and the single generic method is used to print all of the array
elements.
1.1.4 BOUNDED TYPE PARAMETERS
Sometimes it is required to restrict the kinds of types that are allowed to be passed
to a type parameter. Example, a method that operates on numbers might only want
to accept instances of Number or its subclasses. In such cases, bounded type
parameters can be used.
To declare a bounded type parameter, list the type parameter's name, followed by
the extends keyword, followed by its upper bound like below:
class Example <T extends Number>
Example: Program that calculates the average of numbers either integer or
double
package p1;
public class Test<T extends Number> {
T[] numArr; Test(T[]
numArr) { this.numArr
= numArr;
}
public double getAvg() { double
sum = 0.0; for (int i = 0; i <
numArr.length; i++) { sum +=
numArr[i].doubleValue();
}
double avg = sum / numArr.length;
return avg;
}
public static void main(String[] args) {
6
AJAVA-Unit 1: Collection and Generics
Output
Average of Integers = 14.0
Average of Double =2.5
7
Example: Program that demonstrates Upper Bounded Wildcards
import java.util.Arrays; import
java.util.List;
class UpperBoundedWildcardDemo
{
public static void main(String[] args)
{
//Upper Bounded Integer List
List<Integer> list1= Arrays.asList(4,5,6,7);
Output
Total sum is:22.0
Total sum is:15.299999999999999
Here, the sum method is used to calculate the sum of both Integer list and Double
list elements as it accepts list as a parameter whse upper bound is Number.
8
AJAVA-Unit 1: Collection and Generics
Output
[1, 2, 3, 4]
[1, 2, 3, 4]
Here, the print method is used to calculate the print both Integer list and Number
list elements as it accepts list as a parameter whse lower bound is Integer.
9
3. UNBOUNDED WILDCARDS
The unbounded wildcard type is specified using the wildcard character (?), for
example, List<?>. This is called a list of unknown type.
10
AJAVA-Unit 1: Collection and Generics
Output
1
2 3
one
two
three
Here, li and ls are Integer and String lists created from Arrays and both lists are
printed using the generic method printList.
Before Collections, the standard way used for grouping data was using the array,
Vector and HashTable. But all of these have different methods and syntax for
accessing data and performing operations on it. For example, Arrays uses the
square brackets symbol [] to access individual data members whereas Vector uses
the method elementAt(). These differences led to a lot of discrepancies. Thus, the
“Collection Framework” was introduced in JDK 1.2 to bring a unified mechanis m
to store and manipulate a group of objects.
1.3.1 JAVA COLLECTION FRAMEWORK
Any group of objects which are represented as a single unit is known as the
collection of the objects. In Java Collections, individual objects are called as
elements.
The “Collection Framework” holds all the collection classes and interface in it.
These classes and interfaces define all operations that you can perform unifor mly
on different types of data such as searching, sorting, insertion, manipulation, and
deletion.
The Java Collection framework has
1. Interfaces and its implementations, i.e., classes
2. Algorithm
11
1.3.2 JAVA COLLECTION HIERARCHY
The java.util package contains all the classes and interfaces for the Collection
framework.
List
Set
Map
Queue
The Collection classes implement these interfaces and provide plenty of methods
for adding, removing and manipulating data.
1.3.3 ADVANTAGES OF COLLECTION FRAMEWORK
1. Consistent API: The API has a basic set of interfaces like Collection, Set,
List, or Map, all the classes (ArrayList , LinkedList, Vector, etc) that
implement these interfaces have some common set of methods.
2. Reduces programming effort: A programmer doesn’t have to worry about
the design of the Collection but rather he can focus on its best use in his
program. Therefore, the basic concept of Object-oriented programming (i.e.)
abstraction has been successfully implemented.
3. Increases program speed and quality: Increases performance by providing
high-performance implementations of useful data structures and algorithms.
12
AJAVA-Unit 1: Collection and Generics
4. Clean code – These APIs have been written with all good coding practices
and documented very well. They follow a certain standard across whole Java
collection framework. It makes the programmer code look good and clean.
1.3.4 BASIC AND BULK OPERATIONS ON JAVA COLLECTION
The Collection Interface provides methods that performs basic operations on data
such as:
Methods Description
boolean add(E element) Used to add an element in the collection
The Collection Interface also contains methods that performs operations on entire
collections which are also called as bulk operations.
Methods Description
13
void clear() Removes all the elements from the
collection.
Iterator interface
It provides the facility of iterating the elements in a collection.
Method Description
LIST
List in Java provides the facility to maintain the ordered collection. It contains the
index-based methods to insert, update, delete and search the elements. It can have
the duplicate elements also. We can also store the null elements in the list.
The List interface is found in the java.util package and inherits the Collec tio n
interface. It is a factory of ListIterator interface. Through the ListIterator, we can
iterate the list in forward and backward directions.
14
AJAVA-Unit 1: Collection and Generics
int hashcode() It is used to return the hash code value for a list.
boolean isEmpty() It returns true if the list is empty, otherwise false.
It is used to return the index in this list of the last
int lastIndexOf(Object occurrence of the specified element, or -1 if the list
o) does not contain this element.
15
Example: Program that demonstrates List using ArrayList class
Output:
[1, 2]
[1, 1, 2, 3, 2]
[1, 2, 3, 2]
2
[5, 2, 3, 2]
16
AJAVA-Unit 1: Collection and Generics
LinkedList
LinkedList is a class which is implemented in the collection framework which
inherently implements the linked list data structure. It is a linear data structure
where the elements are not stored in contiguous locations and every element is a
separate object with a data part and address part. The elements are linked using
pointers and addresses. Each element is known as a node. Linked List permits
insertion and deletion of nodes at any point in the list in constant time, but do not
allow random access. It permits all elements including null.
Example: Program that demonstrates List using LinkedList class
import java.io.*; import java.util.*;
class LinkedListDemo { public
static void main(String[] args)
{
// Size of the LinkedList
int n = 5;
// Printing elements
System.out.println(ll);
17
Output:
[1, 2, 3, 4, 5]
[1, 2, 3, 5]
1235
1.4.3 ITERATING THROUGH THE LIST
There are multiple ways to iterate through the List. The most famous ways are by
using the basic for loop in combination with a get() method to get the element at
a specific index and the advanced for loop.
Example: Program that iterates through an ArrayList
import java.util.*; public class
ArrayListIteration { public static
void main(String args[])
{
List<String> al= new ArrayList<String>();
al.add("Ann");
al.add("Bill");
al.add(“Cathy”);
System.out.println();
Output:
Ann Bill Cathy
Ann Bill Cathy
18
AJAVA-Unit 1: Collection and Generics
1.5 Set
19
// Adding elements into the HashSet
h.add("India");
h.add("Australia");
h.add("South Africa");
20
AJAVA-Unit 1: Collection and Generics
Example: Program that demonstrates TreeSet implementation
import java.util.*;
Output:
[Australia, India, South Africa]
Set after removing Australia:[India, South Africa]
Iterating over set:
India
South Africa
21
1.6 Maps
The Map interface present in java.util package represents a mapping between a key
and a value. A map contains unique keys and each key can map to at most one
value. Some implementations allow null key and null value like the HashMap and
LinkedHashMap, but some do not like the TreeMap. The order of a map depends
on the specific implementations. For example, TreeMap and LinkedHashMap have
predictable order, while HashMap does not.
The Map interface is not a subtype of the Collection interface. Therefore, it
behaves a bit differently from the rest of the collection types.
The classes which implement the Map interface are HashMap, LinkedHashMap
and TreeMap.
1.6.1 METHODS OF MAP INTERFACE
Method Description
1.6.2 HASHMAP
HashMap class implements the Map interface which allows us to store key and
value pair, where keys should be unique. If you try to insert the duplicate key, it
22
AJAVA-Unit 1: Collection and Generics
will replace the element of the corresponding key. It is easy to perform operations
using the key index like updation, deletion, etc. HashMap class is found in the
java.util package.
HashMap in Java is like the legacy Hashtable class, but it is not synchronized. It
allows us to store the null elements as well, but there should be only one null key.
Since Java 5, it is denoted as HashMap<K,V>, where K stands for key and V for
value.
Output:
vaibhav 20
vishal 10
sachin 30
1.6.3 LINKEDHASHMAP
LinkedHashMap is just like HashMap with an additional feature of maintaining the
order of elements inserted into it. HashMap provided the advantage of quick
insertion, search and deletion but it never maintained the track and order of
insertion which the LinkedHashMap provides where the elements can be accessed
in their insertion order.
23
Example: Program that demonstrates LinkedHashMap implementation
import java.util.*; public class
LinkedHashMapDemo {
public static void main(String[] args)
{
Map<String, Integer> map= new LinkedHashMap<>();
map.put("Angel", 10);
map.put("Liza", 30);
map.put("Steve", 20);
Output:
Angel 10
Liza 30
Steve 20
1.6.4 TREEMAP
The TreeMap in Java is used to implement Map interface and NavigableMap along
with the Abstract Class. It provides an efficient means of storing key-value pairs
in sorted order. TreeMap contains only unique elements and cannot have a null
key but can have multiple null values.
TreeMap is non synchronized and maintains ascending order.
Example: Program that demonstrates TreeMap implementation
import java.util.*;
class TreeMapDemo {
public static void main(String args[]) {
TreeMap<Integer, String> map = new TreeMap<Integer, String>();
24
AJAVA-Unit 1: Collection and Generics
map.put(100, "Angel");
map.put(101, "Chris"); map.put(103,
"Bill"); map.put(102, "Steve");
for (Map.Entry m : map.entrySet()) {
System.out.println(m.getKey() + " " + m.getValue());
}
}
}
Output:
100 Angel
101 Chris
102 Steve
103 Bill
25
Lambda expressions
2.1 Introduction
26
Chapter 2: Lambda Expressions
Output:
Area of square = 100
Here you can note that we are rewriting the method declaration code public void
area() written in the interface again in the anonymous inner class. This repetitive
code can be eliminated if we use Lambda Expressions.
2.1.1 WHAT IS LAMBDA EXPRESSION?
A lambda expression refers to a method that has no name and no access specifier
(private, public, or protected) and no return value declaration. This type of method
is also known as ‘Anonymous methods’, ‘Closures’ or simply ‘Lambdas’. It
provides a way to represent one method interface simply by using an expression
Like anonymous class, a lambda expression can be used for performing a task
without a name.
2.1.2 WHY TO USE LAMBDA EXPRESSIONS?
27
The basic structure of a lambda expression comprises:
Now, we can convert the above method into a lambda expression by removing the
public access specifier, return type declaration, such as void, and the name of
method ‘display’.
The lambda expression is shown as follows:
() -> {
System.out.println(“Hello World”);
}
28
Chapter 2: Lambda Expressions
Output:
Area of square = 100
Here, you can observe that we have not written the method declaration public void
area() present in the interface while implementing it in the class using lambda
expression. Thus reducing repetitive code.
2.1.4 WHERE CAN LAMBDA EXPRESSIONS BE USED?
Lambda Expressions can be written in any context that has a target datatype. The
contexts that have target type are:
• Variable declarations, assignments and array initializers
• Return statements
• Method or constructor arguments
• Ternary Conditional Expressions (?:)
2.2 LAMBDA TYPE INFERENCE
Type Inference means that the data type of any expression (for e.g., a method return
type or parameter type) can be understood automatically by the compiler. Lambda
Expressions support Type Inference. Type inference allows us to not specify
datatypes for lambda expression parameters. Types in the parameter list can be
omitted since java already know the types of the expected parameters for the single
29
abstract method of functional interface. The compiler infers the type of a
parameter by looking elsewhere for the type - in this case the method definition.
Syntax:
(parameter_name1, parameter_name2 …) -> { method body } Example:
interface Operation{
int add(int a,int b);
}
Output:
30
Here, the compiler can infer that a and b must be int because the lambda
expression is assigned to a Operation reference variable.
2.3 LAMBDA PARAMETERS
30
Chapter 2: Lambda Expressions
Output
Hello
• When there is a single parameter, if its type is inferred, it is not mandatory
to use parentheses.
For Example:
(str) -> { System.out.println(“Single Parameter Lambda Expression” + str); }
Example: Program demonstrating Lambda Expression with Single Parameter
//Functional Interface interface
MyFunctionalInterface { //A
method with single parameter
public void say(String str);
} public class SingleParamLambda {
public static void main(String args[]) {
// lambda expression
MyFunctionalInterface msg = (str) -> {
System.out.println(str);
};
msg.say("Hello World");
}
}
31
Output
Hello World
• When there are multiple parameters, they are enclosed in parentheses and
separated by commas.
For Example:
(str1, str2) ->{
System.out.println(“Multiple Parameter Lambda Expression ” +str1+ str2); }
Example: Program demonstrating Lambda Expression with Multiple
Parameters
//Functional Interface interface
MyFunctionalInterface { //A method
with single parameter public void
say(String str1, String str2);
} public class SingleParamLambda {
public static void main(String args[]) {
// lambda expression
MyFunctionalInterface msg = (str1, str2) -> {
System.out.println(str1 +" "+ str2);
};
msg.say("Hello", "Java");
}
}
Output
Hello Java
2.4 LAMBDA FUNCTION BODY
• The body of a lambda expression, and thus the body of the function /
method it represents, is specified to the right of the -> in the lambda
declaration.
() -> {
System.out.println("Hello");
};
• A lambda Expression body can have zero to any number of statements.
• Statements should be enclosed in curly braces.
• If there is only one statement, curly brace is not needed.
• When there is more than one statement in body then these must be enclosed
in curly brackets and the return type of the anonymous function is the same
32
Chapter 2: Lambda Expressions
as the type of the value returned within the code block or void if nothing is
returned.
33
}
Output
30
70
34
Chapter 2: Lambda Expressions
Elements of the ArrayList before sorting : [205, 102, 98, 275, 203]
Elements of the ArrayList after sorting : [275, 205, 203, 102, 98]
Output
11.666666666666666
35
2. Write a program to store integer values 1 to 5 in an ArrayList and print all
numbers,even numbers and odd numbers using Lambda expression.
import java.util.ArrayList; class
Test
{ public static void main(String
args[])
{
// Creating an ArrayList with elements 1,2,3,4,5
ArrayList<Integer> arrL = new
ArrayList<Integer>(); arrL.add(1); arrL.add(2);
arrL.add(3); arrL.add(4); arrL.add(5);
}
);
Output
36
Chapter 2: Lambda Expressions
2
4
Displaying odd numbers
1
3
5
3. Write a program using Lambda Expressions to calculate the area of circle
with radius 5.
interface Area {
double calculate(int r);
} class
AreaofCircle {
public static void main(String args[])
{ Area a = (r) -> { double
area = 3.142 * r * r; return (area);
};
System.out.println(a.calculate(5));
}
}
Output:
Area of circle=78.55
37
import java.util.ArrayList;
import java.util.List; class
Student { String name;
int age; int id;
public String getName() {
return name;
}
public int getAge() {
return age;
} public int
getId() { return
id;
}
38
Chapter 2: Lambda Expressions
}
}
Output:
Before Sorting the student data:
Student[ Name:John Age: 22 Id: 1001]
Student[ Name:Steve Age: 19 Id: 1003]
Student[ Name:Kevin Age: 23 Id: 1005]
Student[ Name:Ron Age: 20 Id: 1010]
Student[ Name:Chris Age: 18 Id: 1111] After Sorting the student data by Age:
Student[ Name:Chris Age: 18 Id: 1111]
Student[ Name:Steve Age: 19 Id: 1003]
Student[ Name:Ron Age: 20 Id: 1010]
Student[ Name:John Age: 22 Id: 1001]
Student[ Name:Kevin Age: 23 Id: 1005] After Sorting the student data by Name:
Student[ Name:Chris Age: 18 Id: 1111]
Student[ Name:John Age: 22 Id: 1001]
Student[ Name:Kevin Age: 23 Id: 1005]
Student[ Name:Ron Age: 20 Id: 1010]
Student[ Name:Steve Age: 19 Id: 1003]
39
40