You are on page 1of 37

GEETHANJALI INSTITUTE OF SCIENCE & TECHNOLOGY: NELLORE

Lecture Notes

Course / Branch: B. Tech. / ECE Academic Year: 2022-23


Name of the Subject: Java Programming (20A05505a) Year / Semester: III / I
Name of the Staff: Mr. P. Vijay Bhaskar Reddy Department: CSE

Unit – IV
Multithreading, The Collections Framework
Multithreading: The Java thread model, creating threads, Thread priorities, Synchronizing threads,
Interthread communication.
The Collections Framework (java.util): Collections overview, Collection Interfaces, The Collection
classesArray List, Linked List, Hash Set, Tree Set, Priority Queue, Array Deque. Hashtable, Properties, Stack,
Vector, String Tokenizer, Bit Set, Date, Calendar, Random, Formatter, Scanner.
Multithreading
Differences between multiple processes and multiple threads:
Single tasking: A task means doing some calculation, processing, etc. Generally, a task involves execution
of a group of statements, for example executing a program. In single tasking environment, only one task is
given to the processor at a time. This means we are wasting a lot of processor time and microprocessor has to
sit idle without any job for a long time. This is the drawback in single tasking.
Multitasking: To use the processor’s time in an optimum way, we can give it several jobs at a time. This is
called multi tasking. Suppose there are 4 tasks that we want to execute. We load them into the memory as
shown in the following diagram. The memory is dividing into 4 parts and the jobs are loaded there. Now, the
microprocessor has to execute them all at a time. So the processor will take small time duration, like a
millisecond and divide this time between the number of jobs. So we get ¼ millisecond time for each job. This
small part of the processor time is called time slice. It will allot exactly ¼ millisecond time for executing each
of the jobs. Within this time slice, it will try to execute each job.
Suppose, it started at first job, it will spend exactly ¼ millisecond time executing the first job. Within this time
duration, if it could not complete the first job, then it stores the intermediate results till then it obtained in a
temporary memory, and then it goes to the second task. It then spends exactly ¼ millisecond time executing
the second task. Within this time, if it can complete this task, no problem. Suppose it could not complete this
task, then it goes to the third task, storing the results in a temporary memory. Similarly, it will spend exactly
¼ millisecond for third task, and another ¼ millisecond for the fourth task. After executing the fourth task, it
will come back to the first task, in a circular manner. This is called round robin method.

1
The processor, after returning to the first task, again starts execution from the point, where it has left that task
earlier. It will execute the first task exactly for ¼ millisecond this time, and proceeds for the second task and
then third and fourth before coming back to the first task in a round robin way. So if you have submitted the
first job, you can understand that the processor is executing your job for ¼ millisecond and then keeping you
waiting for another ¾ millisecond, while it is going and executing the other tasks. After ¾ millisecond, it is
again coming back to your job and executing your job for another ¼ millisecond time. But you will not be
aware that you are kept waiting for ¾ millisecond time, as this time is very small. You will feel that processor
is spending its time executing your job only. Similarly, the second person who submitted the second job will
also feel that only his job is being executed by the processor. The third and forth persons will also feel the
same way. It is something like all the 4 jobs are executed by the processor simultaneously. This is called multi
tasking.
Generally, we have only one processor in our computer systems. One processor has to execute several tasks
means that it has to execute them in a round robin method. This is not multi tasking, since the processor is
quickly executing the tasks one by one, so quickly that we feel all the jobs are executed by the processor at a
time. Multi tasking can not be real phenomenon with single processor systems. If we want to really achieve
multi tasking, we need computers with multiple processors. The main advantage of multi tasking is to use the
processor time in a better way.
Multi tasking is of two types:
a. Process based multi tasking: In process based multi tasking, several programs are executed at a time,
by the microprocessor.
b. Thread based multi tasking: In thread based multi tasking, several parts of the same program is
executed at a time, by the microprocessor. For example, we have a program, there are 2 parts. These
parts may represent two separate blocks of code or two separate methods containing code. Each part
may perform a separate task. The processor should execute the two parts simultaneously. So the
processor uses 2 separate threads to execute these two parts. Each thread can be imagined as an
individual process that can execute a separate set of statements. If a processor has 2 threads, it can do
2 tasks at a time. This is called thread based multi tasking.
Achieving multi tasking with threads has one advantage, i.e. since the threads are light weight processes, they
use minimum resources of the system.
Uses of threads: Threads can be used for multiple purposes.
1. Threads are mainly used in server side programs to serve the needs of multiple clients on a network or
internet. On internet, a server machine has to cater the needs of thousands of clients, at a time. For this
purpose, if we use threads in the server, they can do various jobs at a time, thus they can handle several
clients.
2. Threads are also used to create games and animation. Animation means moving the objects from one
place to another. In many games, generally we have to perform more than one task simultaneously.
There, threads will be of invaluable help. For example, in a game, a flight may be moving from left to
right. A machine gun should shoot it, releasing the bullets at the flight. These two tasks should happen
simultaneously. For this purpose, we can use 2 threads. One thread will move the flight and the other
one will move the bullet, simultaneously towards the flight.

Thread:
A thread represents a separate path of execution of a group of statements. In a java program, if we write a
group of statements, then these statements are executed by JVM one by one. This execution is called a thread,

2
because JVM uses a thread to execute these statements. This means that in every java program, there is always
a thread running internally. This thread is used by JVM to execute the program statements. Let us write a
program to see what thread is:
E.g.:
//to find currently running thread in this program
class Current
{
public static void main(String args[])
{
System.out.println("Let us find current thread");
Thread t=Thread.currentThread();
System.out.println("Current thread= "+t);
System.out.println("Its name= "+t.getName());
t.setName("vbr");
System.out.println("Its new name= " +t);
}
}
O/P: F:\JAVA>javac thread.java

F:\JAVA>java Current
Let us find current thread
Current thread= Thread[main,5,main]
Its name= main
Its new name= Thread[vbr,5,main]

In the preceding program, currentThread() is a static method in Thread class. So we called it as


Thread.currentThread(). Then this method gave an object t of Thread class. When we displayed this object t,
it displayed its contents as;
Thread [main, 5, main]
Here, Thread indicates that t is a Thread class object. And the first main indicates the name of the thread
running the current code. We get 5 which is a number representing the priority of the thread. Every thread will
have a priority number associated with it. These priority numbers will range from 1 to 10. 1 is the minimum
priority, and 10 is the maximum priority of a thread. If the priority number of a thread is more, it is given more
preference while execution by JVM. The default priority number of a thread is 5.
The next main indicates the thread group name to which this thread belongs. A thread group represents a group
of threads as a single unit. If thread is t, its name can be known by using t.getName() method.

Thread states or life cycle of a thread:


Starting from the birth of a thread, till its death, a thread exists in different states which are collectively called
“thread life cycle”. The life cycle of a thread is represented in the following diagram.

3
1. New state or born state: A thread will born when it is created using Thread class as:
Thread t=new Thread();
2. Runnable (Ready – to – run) state: A thread starts its life from runnable state. A thread first enters
runnable state after the invoking of start() method. yield() method may pause a thread briefly, but the
thread will be still in runnable state only.
3. Running state: A thread is in running state which means the thread is currently executing. There are
several ways to enter in Runnable state but there is only one way to enter in running state.
4. Not – runnable state or blocked state: From runnable state, a thread may get into not – runnable
state, when sleep() or wait() methods act on it. A thread may be occasionally blocked on some input –
output device where it is expecting some input – output from the user. The thread would be in not –
runnable state till the user provides the required input or output. After coming out from not – runnable
state, again the thread comes back to runnable state.
5. Dead state: Finally, a thread is terminated from memory only when it comes out of run() method. this
happens when the thread completely executes the run () method and naturally comes out, or when the
user forces it to come out of run() method.
As we have seen different states that may be occur with the single thread, a running thread can enter to any
non – runnable state, depending on the circumstances. A thread can not enter directly to the running state from
non- runnable state, first it goes to runnable state. Now let’s understand some non – runnable states which
may be occur while handling the multiple threads.
6. Sleeping: On this state, the thread is still alive but it is not runnable, it might return to runnable state
later, if a particular event occurs. On this state a thread sleeps for a specified amount of time, you can
use the method sleep() to stop the running state of a thread.
static void sleep(long millisecond) throws InterruptedException

7. Waiting: A thread waits for notification from another thread. The thread sends back to runnable state
after sending notification from another thread.
final void wait(long timeout) throws InterruptedException
final void wait(long timeout, int nanos) throws InterruptedException
final void wait() throws InterruptedException

Creating threads:
We know that in every java program, there is a main thread available already. Apart from this main thread,
we can also create our own threads in a program. The following steps should be used:

4
1. Create a class that extends Thread class or implements Runnable interface. Both the Thread class
and Runnable interface are found in java.lang package.
class myclass extends Thread
or
class myclass implements Runnable
2. Now in this class, write a run() method as:
public void run()
{
Statements;
}
By default, this run() method is recognized and executed by a thread.
3. Create an object to myclass, so that the run() method is available for execution.
myclass obj=new myclass();
4. Now, create a thread and attach the thread to the object obj.
Thread t=new Thread(obj);
Or
Thread t=new Thread(obj, “threadname”);
5. Run the thread, for this purpose, we should use start() method of Thread class.
t.start();
Now, the thread will start execution on the object of myclass. In that object, run() method is found, hence it
will execute the statements inside the run() method.
E.g.:
//to create a thread and run it
//let the class extends Thread or implements Runnable
import java.io.*;
class MyThread extends Thread
{
//write run() method inside the class
public void run()
{
//only this code is executed by the thread
for(int i=1; i<=10000; i++)
{
System.out.println(i);
}
}
}
class Demo
{
public static void main(String args[])
{
//create an object to MyThread class
MyThread obj=new MyThread();
//create a thread and attach it to the object of MyThread class
Thread t=new Thread(obj);
//now run the thread on the object

5
t.start(); //now this thread will execute the code inside run()
//method of MyThread object
}
}

O/P: F:\JAVA>javac demo.java


F:\JAVA>java Demo
1
2
3
4
5
As a result, the numbers will be displayed starting from 1 to 100000. If you want to terminate the program in
the middle, you can press Ctrl+C from the keyboard. This leads to abnormal program termination. It means
the entire program is terminated, not just the thread. Abnormal program termination may cause loss of data
and lead to lead to unreliable results. So we should terminate the thread only, not the program.

Terminating the thread;


A thread will terminate automatically when it comes out of run() method. To terminate the thread on our own,
the following steps can be used:
1. Create a boolean type variable and initialize it to false.
boolean stop=false;
2. Let us assume that we want to terminate the thread when the user press <Enter> key. So, when the
user presses that button, make the boolean type variable as true.
stop=true;
3. Check this variable in run() method and when it is true, make the thread return from the run()
method.
public void run()
{
if(stop==true)
return;
}
E.g.:
//to crate a thread and run it, then stop it
import java.io.*;
class MyThread extends Thread
{
boolean stop=false;
public void run()
{
//only this code is executed by the thread
for(int i=1; i<=10000; i++)
{
System.out.println(i);
if(stop) return; //come out of run()
}

6
}
}
class Demo
{
public static void main(String args[])throws IOException
{
//create an object to MyThread class
MyThread obj=new MyThread();

//create a thread and attach it to the object of MyThread class


Thread t=new Thread(obj);

//noe run the thread on the object


t.start(); //now this thread will execute the code inside run()
//method of MyThread object
//stop the thread when the enter key is pressed
System.in.read(); //wait till enter key pressed
obj.stop=true;
}
}

O/P: F:\JAVA>javac thread1.java

F:\JAVA>java Demo
1
2
3
4
5

Single tasking using thread:


A thread can be employed to execute one task at a time. Suppose there are 3 tasks to be executed. We can
create a thread and pass the 3 tasks one by one to the thread. For this purpose, we can write all these tasks
separately in separate methods: task1(), task2(), task3(). Then these methods should be called from the run()
method, one by one. A thread executes only the code inside the run() method. It can never execute other
methods unless they are called from run().
E.g.:
//single tasking using a thread
class Mythread extends Thread
{
public void run()
{
//execute the tasks one by one by calling methods
task1();
task2();
task3();

7
}
void task1()
{
System.out.println("This is task 1");
}
void task2()
{
System.out.println("This is task 2");
}
void task3()
{
System.out.println("This is task 3");
}
}
class Single
{
public static void main(String args[])
{
Mythread obj=new Mythread();

//create a thread t1 and attach it to that object


Thread t1=new Thread(obj);

//execute the thread t1 on that object's run() method


t1.start();
}
}
O/P: F:\JAVA>javac singletask.java
F:\JAVA>java Single
This is task 1
This is task 2
This is task 3

Multi tasking using threads:


In multi tasking, several tasks are executed at time. For this purpose, we need more than one thread. For
example, to perform 2 tasks, we can take 2 threads and attach them to the 2 tasks. Then those tasks are
simultaneously executed by the 2 threads. Using more than one thread is called ‘multi tasking’.
E.g.:
//Two threads performing two tasks at a time - theatre example
class Mythread implements Runnable
{
//declare a string to represent the task

String str;
Mythread(String str)
{

8
this.str=str;
}
public void run()
{
for(int i=1; i<=10; i++)
{
System.out.println(str+ " : "+i);
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
ie.printStackTrace();
}
}
}
}
class Theatre
{
public static void main(String args[])
{
//create 2 objects to represent 2 tasks
Mythread obj1=new Mythread("Cut the ticket");
Mythread obj2=new Mythread("Show the seat");
//create 2 threads and attach them to the 2 objects
Thread t1=new Thread(obj1);
Thread t2=new Thread(obj2);
//start the threads
t1.start();
t2.start();
}
}
O/P: F:\JAVA>javac multitask.java
F:\JAVA>java Theatre
Cut the ticket : 1
Show the seat : 1
Show the seat : 2
Cut the ticket : 2
Cut the ticket : 3
Show the seat : 3
Show the seat : 4
Cut the ticket : 4
Show the seat : 5
Cut the ticket : 5
Show the seat : 6

9
Cut the ticket : 6
Show the seat : 7
Cut the ticket : 7
Show the seat : 8
Cut the ticket : 8
Cut the ticket : 9
Show the seat : 9
Show the seat : 10
Cut the ticket : 10
In the preceding example, sleep() is a static method in Thread class, which is used to suspend execution of a
thread from some specified milliseconds. Since this method can throw InterruptedException, we caught it in
catch block.
Multiple threads acting on single object:
We have used 2 threads on the 2 objects of any class. It is also possible to use 2 or more threads on a single
object. But in this case, sometimes we get unreliable results. First let us see why 2 threads should share the
same object (same run() method). We write an object to represent one task. If there is a different task, we take
another object. When two people (threads) perform same task, then they need same object (run() method) to
be executed each time.
E.g.:
//Thread unsafe - Two threads acting on same object
class Reserve implements Runnable
{
//available berths are 1
int available=1;
int wanted;

//accept wanted berths at run time


Reserve(int i)
{
wanted=i;
}
public void run()
{
//display available berths
System.out.println("Available Berths= "+available);
//if available berths are more than wanted berths
if(available >= wanted)
{
//get the name of the passenger
String name=Thread.currentThread().getName();
//allot the berth to him
System.out.println(wanted +" Berth reserved for " +name);
try
{
Thread.sleep(1000); //wait for printing the ticket
//update the no. of available berths

10
available=available - wanted;
}
catch(InterruptedException ie)
{
}
}
//if available berths are less, display sorry
else
System.out.println("Sorry, no berths");
}
}
class Unsafe
{
public static void main(String args[])
{
//tell that 1 berth is needed
Reserve obj=new Reserve(1);

//attach first thread to the object


Thread t1=new Thread(obj);
//attach second thread to the same object
Thread t2=new Thread(obj);

//take the thread names as person names


t1.setName("First person");
t2.setName("Second person");
//send the requests for berth
t1.start();
t2.start();
}
}
O/P: F:\JAVA>javac reserve.java

F:\JAVA>java Unsafe
Available Berths= 1
Available Berths= 1
1 Berths reserved for First person
1 Berths reserved for Second person
Please observe the output in the preceding program. It is meaningless. It has allocated the same berth to both
the passengers. In this program, already we have taken available berths as 1. When thread t1 enters the run()
method, it sees available number of berths as 1 and hence, it allots it to first person. Then it enters try{} block
inside run() method, where it sleep for 1 second. In this time the ticket will be printed on the printer. When
the first thread is sleeping, thread t2 also enters the run() method, it also sees that there is 1 berth remaining.
The reason is for this is that the available number of berths is not yet updated by the first thread. So the second
thread also sees 1 berth as available, and it allots the same berth to the second person. Then the thread t2 will
also go into sleep state. Thread t1 wakes up first, and then it updates the available number of berths as 0. But

11
by this time, the second thread has already allotted the same berth to the second person also. Since both the
threads are acting on the same object simultaneously, the result is unreliable.
This means we are preventing the threads to act on the same object simultaneously. This is called thread
synchronization or thread safe.

Synchronizing threads:
When a thread is already acting on an object, preventing any other thread from acting on the same object is
called Thread synchronization or Thread safe. The object on which the threads are synchronized is called
synchronized object. Thread synchronization is recommended when multiple threads are used on the same
object. There are two ways of synchronizing the object.
1. Using synchronized block: Here, we can embed a group of statements of the object (inside run()
method) within a synchronized block as shown below.
synchronized(object)
{
Statements;
}
Here, object represents the object to be locked or synchronized. The statements inside the synchronized
block are all available to only one thread at a time. They are not available to more than one thread
simultaneously.
2. Using synchronized keyword: We can synchronize an entire method by using synchronized keyword.
For example, if we want to synchronize the code of display() method, then add the synchronized
keyword before the method name as shown here:
synchronized void display()
{
Statements;
}
Now the statements inside the display() method are not available to more than one thread at a time.
This method code is synchronized.
E.g.:
//Thread synchronization - Two threads acting on same object
class Reserve implements Runnable
{
//available berths are 1
int available=1;
int wanted;

//accept wanted berths at run time


Reserve(int i)
{
wanted=i;
}
public void run()
{
synchronized(this)
{
//display available berths

12
System.out.println("Available Berths= "+available);
//if available berths are more than wanted berths
if(available >= wanted)
{
//get the name of the passenger
String name=Thread.currentThread().getName();
//allot the berth to him
System.out.println(wanted +" Berths reserved for " +name);
try
{
Thread.sleep(1000); //wait for printing the ticket
//update the no. of available berths
available=available - wanted;
}
catch(InterruptedException ie)
{
}
}
//if available berths are less, display sorry
else
System.out.println("Sorry, no berths");
}
}
}
class Safe
{
public static void main(String args[])
{
//tell that 1 berth is needed
Reserve obj=new Reserve(1);

//attach first thread to the object


Thread t1=new Thread(obj);
//attach second thread to the same object
Thread t2=new Thread(obj);

//take the thread names as person names


t1.setName("First person");
t2.setName("Second person");

//send the requests for berth


t1.start();
t2.start();
}
}
O/P: F:\JAVA>javac threadsafe.java

13
F:\JAVA>java Safe
Available Berths= 1
1 Berths reserved for First person
Available Berths= 0
Sorry, no berths

Thread priorities:
When the threads are created and started, a ‘thread scheduler’ program in JVM will load them into memory
and execute them. This scheduler will allot more JVM time to those threads which are having higher priorities.
The priority numbers of a thread will change from 1 to 10. The minimum priority of a thread is 1, and the
maximum priority is 10. The normal priority of a thread is 5.
To set the priority of a thread: t.setPriority(int priority_no);
Thread.MAX_PRIORITY value is 10.
Thread.MIN_PRIORITY value is 1.
Thread.NORM_PRIORITY value is 5.
When two tasks are assigned to two threads with different priorities, example, 2 and 5, then the thread with
priority number 5 will be given more JVM time and hence it will complete the task earlier than the thread with
priority number 2.
E.g.:
//Thread priorities
class Myclass extends Thread
{
int count=0; //this counts the numbers
public void run()
{
for(int i=1; i<=10000; i++)
count++; //count numbers upto 10000
//display which thread has completed counting and its priority
System.out.println("Completed thread: "+
Thread.currentThread().getName());
System.out.println("Its priority: "+
Thread.currentThread().getPriority());
}
}
class Prior
{
public static void main(String args[])
{
Myclass obj=new Myclass();
//create 2 threads
Thread t1=new Thread(obj, "One");
Thread t2=new Thread(obj, "Two");
//set priorities for them
t1.setPriority(2);
t2.setPriority(Thread.NORM_PRIORITY);

14
//this means priority no. 5
//start first t1 and then t2
t1.start();
t2.start();
}
}
O/P: F:\JAVA>javac priority.java
F:\JAVA>java Prior
Completed thread: Two
Its priority: 5
Completed thread: One
Its priority: 2
Thread class methods:
Some important methods of java.lang.Thread class as:
 To create a thread, we can use the following forms:
Thread t1=new Thread();
Thread t1=new Thread(obj);
Thread t1=new Thread(obj, ‘threadname”);
 To know the currently running thread:
Thread t=Thread.currentThread();
 To start a thread:
t.start();
 To stop execution of a thread for specified time:
Thread.sleep(milliseconds);
 To get the name of a thread:
String name=t.getName();
 To set a new name to a thread:
t.setName(“newname”);
 To get the priority of a thread:
int priority_no=t.getPriority();
 To set the priority of a thread:
t.setPriority(int priority_no);
 To test if a thread is still alive:
t.isLive(); // returns true or false.
 To wait till a thread dies
t.join();

Thread Groups:
Based on the functionality we can group threads as a single unit which is nothing but thread group. Thread
group provides a convenient way to perform common operations for all the threads belonging to a particular
group. For example, stop all printing threads, and all producer threads should wait until completion of all
consumer threads.
A thread group represents several threads as a single group. The main advantage of taking several threads as
a group is that by using single method, we will be able to control all the threads in the group.
To create a thread group, we should simply create an object to ThreadGroup class as:
ThreadGroup tg=new ThreadGroup(“Groupname”);
15
Here, tg is the thread group object, and group name is its name.
To add a thread to this group (tg):
Thread t1=new Thread(tg, targetobject, “threadname”);
Here, t1 thread is created and added to the thread group tg. This thread acts on targetobject, which is the target
object for the thread. The thread name represents the name of the thread t1.
To add another thread group (tg1) to this group (tg):
ThreadGroup tg1=new ThreadGroup(tg, “groupname”);
Here we are creating and adding the thread group tg1 to the thread group tg. The name of the added thread
group is represented by groupname.
To know the parent of a thread, we can use getParent().
tg.getParent();
This method returns ThreadGroup object which is the parent of tg.
To know the parent thread group of a thread, we can use:
t.getThreadGroup();
This returns a parent ThreadGroup object to which the thread t belongs.
To know the number of threads actively running in a thread group:
Tg.activeCount();
This method returns an integer number that gives the number of threads in tg which are currently running in
memory.
To change the maximum priority of a thread group tg:
Tg.setMaxPriority();
Normally, the maximum priority of a thread group will be 10. But this method can set it as any other number
between 1 and 10.
E.g.:
//using thread groups
class TGroups
{
public static void main(String args[])throws Exception
{
Reservation res=new Reservation();
Cancellation can=new Cancellation();

//create a thread group with name


ThreadGroup tg=new ThreadGroup("First Group");

//create 2 threads and add them to First Group


Thread t1=new Thread(tg, res, "First Thread");
Thread t2=new Thread(tg, res, "Second Thread");

//create another thread group tg1 as a child to tg


ThreadGroup tg1=new ThreadGroup(tg, "Second Group");

//create 2 threads and add them to Second Group


Thread t3=new Thread(tg1, can, "Third Thread");
Thread t4=new Thread(tg1, can, "Fourth Thread");

16
//find parent group of tg1
System.out.println("parent of tg1= "+tg1.getParent());

//set maximum priority to tg1 as 7


tg1.setMaxPriority(7);

//know the thread group of t1 and t3


System.out.println("Thread group of t1= "+t1.getThreadGroup());
System.out.println("Thread group of t3= "+t3.getThreadGroup());

//start the threads


t1.start();
t2.start();
t3.start();
t4.start();

//find how many threads are actively running


System.out.println("No. of threads active in tg= "+tg.activeCount());
}
}
class Reservation extends Thread
{
public void run()
{
System.out.println("I am reservation thread");
}
}
class Cancellation extends Thread
{
public void run()
{
System.out.println("I am cancellation thread");
}
}
O/P: E:\vbr\JAVA>javac threadgroup.java

E:\vbr\JAVA>java TGroups
parent of tg1= java.lang.ThreadGroup[name=First Group,maxpri=10]
Thread group of t1= java.lang.ThreadGroup[name=First Group,maxpri=10]
Thread group of t3= java.lang.ThreadGroup[name=Second Group,maxpri=7]
I am reservation thread
No. of threads active in tg= 3
I am reservation thread
I am cancellation thread
I am cancellation thread

17
Types of threads:
Java allows us to create two types of threads. They are
1. Non – daemon threads: A thread that executes main logic of the project is called non – daemon
thread. We can’t change the nature of main thread to daemon because it is started by JVM. Hence, it
is impossible.
2. Daemon threads: A thread that is running in background to provide services to non – daemon threads
is called daemon thread. Hence, we can say daemon threads are service threads. Sometimes, a thread
has to continuously execute without any interruption to provide services to other threads. For example,
oracle.exe is a program or a thread that continuously executes in a computer. When the system is
switched on, it also starts running and will terminate only when the system is off. Any other threads
like SQL+ can communicate with it to store or retrieve data. Daemon thread generally provides a
background processing.
To make a thread t as a daemon thread, we can use setDaemon() method as:
t.setDaemon();
To know if a thread is daemon or not, isDaemon() is useful.
boolean x=t.isDaemon();
If isDaemon() returns true, then the thread t is a daemon thread, otherwise not.
E.g.:
class mydaemon extends Thread
{
public static void main(String args[])
{
mydaemon myd=new mydaemon();
myd.setDaemon(true);
myd.start();
}
}

Thread communication:
In some cases, two or more threads should communicate with each other. For example, a consumer thread is
waiting for a producer to produce the data. When the producer thread completes production of data, then the
consumer thread take that data and use it.
In the producer thread class, we take a StringBuffer object to store data; in this case, we take some numbers
from 1 to 10. These numbers are added to StringBuffer object. We take another boolean variable dataprodover,
and initialize it to false. When the production of numbers is completed to make this dataprodover will be true.
Producing data is done by appending numbers to StringBuffer using for loop. This may take some time. When
appending is over, we come out of loop and then store true into dataprodover. When the producer is busy
producing the data, now and then the consumer will check if dataprodover is true or not. If dataprodover is
true, the consumer takes the data from StringBuffer and uses it. If the dataprodover shows false, then consumer
will sleep for some time and then again checks the dataprodover. In this way, the producer and consumer can
communicate with each other.
E.g.:
/*This program shows how two threads can communicate with each other.
This is inefficient way of communication*/
class Producer extends Thread
{
18
//to add data, use StringBuffer object
StringBuffer sb=new StringBuffer();

//dataprodover will be true when data production is over


boolean dataprodover=false;

public void run()


{
//go on appending data to StringBuffer
for(int i=1; i<=10; i++)
{
try
{
sb.append(i+":");
Thread.sleep(100);
System.out.println("Appending");
}
catch(Exception e)
{
}
}
//data production is over, so store true into dataprodover
dataprodover=true;
}
}
class Consumer extends Thread
{
/*create Producer reference to refer to Producer object
from Consumer class*/
Producer prod;
Consumer(Producer prod)
{
this.prod=prod;
}
public void run()
{
/*if data production is not over, sleep for 1000 milliseconds
and check again. Here there is a time delay of several
milliseconds to receive data*/
try
{
while( ! prod.dataprodover)
Thread.sleep(10000);
}
catch(Exception e)
{

19
}
//when data production is over, display data of StringBuffer
System.out.println(prod.sb);
}
}
class Communicate
{
public static void main(String args[])throws Exception
{
//producer produces some data which consumer consumes
Producer obj1=new Producer();

/*pass Producer object to Consumer so that it is then


available to Consumer*/
Consumer obj2=new Consumer(obj1);

//create 2 threads and attach to Producer and Consumer


Thread t1=new Thread(obj1);
Thread t2=new Thread(obj2);

//run the threads


t2.start(); //Consumer waits
t1.start(); //Producer starts production
}
}
But this is not efficient way of communication. Why because consumer checks the dataprodover at some point
of time, and finds it false. So it goes into sleep for the next 10 milliseconds. Meanwhile, the data production
may be over. But consumer comes out of sleep after 10 milliseconds and then only it can find dataprodover is
true. This means that there may be a time delay of 1 to 9 milliseconds to receive the data after its actual
production is completed.
Now we improve the efficiency of communication between threads by using the following methods of
java.lang.Object class.
1. obj.notify(): This method releases an object and sends a notification to a waiting thread that the object
is available.
2. obj.notifyAll(): This method is useful to send notification to all waiting threads at once that the object
is available.
3. obj.wait(): This method makes a thread wait for the object till it receives a notification from a notify()
or notifyAll() methods.
Let us re – write the producer – consumer program using the above the methods so that there will not be any
wastage of a single millisecond time to receive the data by the consumer. In this program, there is no need to
use dataprodover variable at producer side. We can directly send a notification immediately after the data
production is over.
E.g.:
/*This program shows how to use wait and notify
This is the most efficient way of thread communication*/
class Producer extends Thread

20
{
//to add data, use StringBuffer object
StringBuffer sb=new StringBuffer();

public void run()


{
synchronized(sb)
{
//go on appending data to StringBuffer
for(int i=1; i<=10; i++)
{
try
{
sb.append(i+":");
Thread.sleep(1000);
System.out.println("Appending");
}
catch(Exception e)
{
}
}
//data production is over, so notify to Consumer thread
sb.notify();
}
}
}
class Consumer extends Thread
{
/*create Producer reference to refer to Producer object
from Consumer class*/
Producer prod;
Consumer(Producer prod)
{
this.prod=prod;
}
public void run()
{
synchronized(prod.sb)
{
/*wait till a notification is received from Producer thread.
Here there is no wastage of time of even a single millisecond*/
try
{
prod.sb.wait();
}
catch(Exception e)

21
{
}
//when data production is over, display data of StringBuffer
System.out.println(prod.sb);
}
}
}
class Communicate
{
public static void main(String args[])throws Exception
{
//producer produces some data which consumer consumes
Producer obj1=new Producer();

/*pass Producer object to Consumer so that it is then


available to Consumer*/
Consumer obj2=new Consumer(obj1);

//create 2 threads and attach to Producer and Consumer


Thread t1=new Thread(obj1);
Thread t2=new Thread(obj2);

//run the threads


t2.start(); //Consumer waits
t1.start(); //Producer starts production
}
}

O/P: F:\JAVA>javac communication1.java

F:\JAVA>java Communicate
Appending
Appending
Appending
Appending
Appending
Appending
Appending
Appending
Appending
Appending
1:2:3:4:5:6:7:8:9:10:
Here, sb.notify() is sending a notification to the consumer thread that the StringBuffer object sb is available,
and can be used now. Here, there is no need of using sleep() method to go into sleep for sometime. wait()
method stops waiting as soon as it receives the notification. So there is no time delay to receive the data
from the producer.

22
Introduction to java collections:
How can we handle a group of elements? We use an array to store a group of elements and handle them easily.
Then, how can we handle a group of objects? Can we use an array to store a group of objects? Yes, it is
possible to use an array to store a group of objects.

Using an array to store a group of objects:


import java.io.*;
class Employee
{
int id;
String name;
Employee(int i, String n)
{
id=i;
name=n;
}
void displaydata()
{
System.out.println(id+"\t"+name);
}
}
class Demo
{
public static void main(String a[])throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Employee arr[]=new Employee[5];
for(int i=0; i<5; i++)
{
System.out.println("Enter id=");
int id=Integer.parseInt(br.readLine());
System.out.println("Enter name=");
String name=br.readLine();
arr[i]=new Employee(id,name);
}
System.out.println("\n The Employee data is:");
for(int i=0; i<arr.length; i++)
{
arr[i].displaydata();
}
}
}

O/P: F:\JAVA>javac arrays1.java


F:\JAVA>java Demo

23
Enter id=057
Enter name=bsk
Enter id=058
Enter name=
dsr
Enter id=
315
Enter name=
vbr
Enter id=
391
Enter name=
takk
Enter id=
495
Enter name=
kv

The Employee data is:


57 bsk
58 dsr
315 vbr
391 takk
495 kv

But there are also certain inconveniences in this mechanism. They are as follows:
 Arrays can not grow dynamically. This means, once an array is created, its size is fixed and at runtime
its size can not be increased or decreased.
 We can not store different class objects into the same array. The reason is that an array can store only
one data type of elements.
 Adding the objects at the end of the array is easy. But, inserting and deleting the elements in the middle
of the array is difficult. In this case, we have rearranged all the elements of the array.
 Retrieving the elements from an array is easy but after retrieving the elements, if we want to process
them, then there are no methods available to carry out this.
Due to these problems, programmers want a better mechanism to store a group of objects. The alternative is
using an object to store a group of other objects. It means that we can use a class object as an array. Such an
object is called collection object or container object.

Overview of java collection frame work:


A collection object or a container object is an object which can store a group of other objects. A collection
object has a class called as collection class or container class. All the collection classes are available in the
package java.util. A group of collection classes is called a collection frame work.
Collection object does not store the physical copies of other objects. Since the other objects are already
available in memory. Storing another copy of them into the collection object would be a wasting of memory.
So, JVM does not store the copies of other objects, it simply stores the references of other objects into a
collection object.

24
All the collection classes in java.util package are the implementation classes of different interfaces as shown
in the following table.

Interface type Implementation classes


Set<T> HashSet<T>
LinkedHashSet<T>
List<T> Stack<T>
LinkedList<T>
ArrayList<T>
Vector<T>
Queue<T> LinkedList<T>
Map<K, V> HashMap<K, V>
HashTable<K, V>

Sets: A Set represents a group of elements arranged just like an array. The set will grow dynamically when
the elements are stored into it. A set will not allow duplicate elements. If we try to pass the same element that
is already available in the set, then it is not stored into the set.
Lists: Lists are like sets. They store a group of elements. But lists allow duplicate values to be stored.
Queues: A Queue represents arrangement of elements in FIFO (First In First Out) order. This means that an
element that is stored as a first element into the queue will be removed first from the queue.
Maps: Maps store elements in the form of key and value pairs. If the key is provided then its corresponding
value can be obtained. The keys should have unique values.
In all the cases the elements refer to objects only. This means we can not store primitive data types in the
collection objects. We can store only objects since the main aim of collections is to handle objects only, not
the primitive data types.

Retrieving elements from collections:


Following are the 4 ways to retrieve any element from a collection object:
 Using for – each loop.
 Using Iterator interface.
 Using ListIterator interface.
 Using Enumeration interface.

for – each loop:


for – each loop is like for loop which repeatedly executes a group of statements for each element of the
collection. The syntax is
for(variable: collection-object)
{
Statements;
}
Here, the variable assumes each element of the collection-object and the loop is executed as many times as
there are number of elements in the collection-object. If collection-object has n elements the loop is executed
exactly n times and the variable stores each element in each step.

Iterator interface:
Iterator is an interface that contains methods to retrieve the elements one by one from a collection object. It
has 3 methods:

25
 boolean hasNext(): This method returns true if the iterator has more elements.
 element next(): This method returns the next element in the iterator.
 void remove(): This method removes from the collection the last element returned by the iterator.

ListIterator interface:
ListIterator is an interface that contains methods to retrieve the elements from a collection object, both in
forward and reverse directions. It has the following methods:
 boolean hasNext(): This method returns true if the ListIterator has more elements when traversing the
list in the forward direction.
 boolean hasPrevious(): This method returns true if the ListIterator has more elements when traversing
the list in the reverse direction.
 element next(): This method returns the next element in the list.
 element previous(): This method returns the previous element in the list.
 void remove(): This method removes from the list the last element returned by the next() or previous()
methods.

Enumeration interface:
This interface is useful to retrieve one by one the elements like the Iterator. It has 2 methods:
 boolean hasMoreElements(): This method tests if the Enumeration has any more elements or not.
 element nextElement(): This returns the next element that is available in Enumeration.

Commonly used collection classes:


ArrayList class:
An ArrayList is like an array, which can grow in memory dynamically. It means that when we store elements
into the ArrayList, depending on the number of elements, the memory is dynamically allotted and re-allotted
to accommodate all the elements. ArrayList is not synchronized. This means that when more than one thread
acts simultaneously on the ArrayList object, the results may be incorrect in some cases. The ArrayList can be
written as:
class ArrayList<D>
Where D represents the type of elements to be stored into the ArrayList. For example, to store String type
elements, we can create an object to ArrayList as:
Arraylist<String> a=new ArrayList<String>();
The preceding statement constructs an ArrayList with a default initial capacity of 10. We can also mention the
capacity at the time of creating ArrayList object as:
ArrayList<Double> a1=new ArrayList<Double>(101);
ArrayList class methods:
ArrayList includes the following methods:
 boolean add(element obj): This method appends the specified element to the end of the ArrayList. If
the element is added successfully then the preceding method returns true.
 void add(int position, element obj): This method inserts the specified element at the specified
position in the ArrayList.
 element remove(int position): This method removes the element at the specified position in the
ArrayList. This method also returns the element which was removed from the ArrayList.
 boolean remove(Object obj): This method removes the first occurrence of the specified element obj
from the ArrayList, if it is present.
 void clear(): This method removes all the elements from the ArrayList.
26
 element set(int position, element obj): This method replaces an element at the specified position in
the ArrayList with the specified element obj.
 boolean contains(Object obj): This method returns true if the ArrayList contains the specified
element obj.
 element get(int position): This method returns the element available at the specified position in the
ArrayList.
 int indexOf(Object obj); This method returns the position of the first occurrence of the specified
element obj in the list, or -1 if the element is not found in the list.
 int lastIndexOf(Object obj); This method returns the position of the last occurrence of the specified
element obj in the list, or -1 if the element is not found in the list.
 int size(): This method returns the number of elements present in the ArrayList.
 Object[ ] toArray(): This method returns an Object class type array containing all the elements in the
ArrayList in proper sequence.

E.g.: The following program illustrates how to create an ArrayList with strings and perform various
operations on it.
//ArrayList with String objects
import java.util.*;
class ArrayListDemo
{
public static void main(String args[])
{
//create ArrayList
ArrayList<String> arl=new ArrayList<String>();
//add 4 objects
arl.add("Apple");
arl.add("Mango");
arl.add("Grapes");
arl.add("Guava");
//display contents
System.out.println("Contents: "+arl);
//remove 2 objects
arl.remove(3);
arl.remove("Apple");
//display again
System.out.println("Contents after removing: "+arl);
//display its size
System.out.println("Size of ArrayList: "+arl.size());
//extract elements using iterator
System.out.println("Extracting using Iterator:");
//add an Iterator to ArrayList to retrieve elements
Iterator it=arl.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}

27
arl.set(1,"Banana");
System.out.println("Contents: "+arl);
arl.add("Apple");
arl.add("Mango");
arl.add("Grapes");
arl.add("Guava");
arl.add("Orange");
System.out.println("Contents: "+arl);
int a=arl.indexOf("Grapes");
System.out.println("The position of the first occurence of the Grapes: " +a);
int b=arl.lastIndexOf("Mango");
System.out.println("The position of the last occurence of the Mango: " +b);
System.out.println("The element available in the first position: " +arl.get(1));
}
}
O/P: F:\JAVA>javac arraylist.java

F:\JAVA>java ArrayListDemo
Contents: [Apple, Mango, Grapes, Guava]
Contents after removing: [Mango, Grapes]
Size of ArrayList: 2
Extracting using Iterator:
Mango
Grapes
Contents: [Mango, Banana]
Contents: [Mango, Banana, Apple, Mango, Grapes, Guava, Orange]
The position of the first occurence of the Grapes: 4
The position of the last occurence of the Mango: 3
The element available in the first position: Banana
LinkedList class:
A LinkedList contains a group of elements in the form of nodes. Each node will have 3 fields – the data filed
contains data and the link fields contain references to previous and next nodes. The following diagram displays
that how the traversing in the linked list is done using these link fields. LinkedList is very convenient to store
data. Inserting the elements into the linked list and removing the elements from the linked list is done quickly
and takes the same amount of time.
A linked list written in the form of:
class LinkedList<E>
We can create an empty linked list for storing String type elements (objects) as:
LinkedList<String> l=new LinkedList<String>();
LinkedList class methods:
LinkedList includes the following methods:
 boolean add(element obj): This method appends the specified element to the LinkedList. If the
element is added successfully then the preceding method returns true.
 void add(int position, element obj): This method inserts the specified element obj into the linked list
at specified position.

28
 void addFirst(element obj): This method inserts the specified element obj at the first position of the
linked list.
 void addLast(element obj): This method inserts the specified element obj to the end of the linked list.
 element removeFirst(): This method removes the first element from the LinkedList and returns it.
 element removeLast(): This method removes the last element from the LinkedList and returns it.
 element remove(int position): This method removes the element at the specified position in the
LinkedList. This method also returns the element which was removed from the LinkedList.
 void clear(): This method removes all the elements from the LinkedList.
 element set(int position, element obj): This method replaces an element at the specified position in
the list with the specified element obj.
 element get(int position): This method returns the element available at the specified position in the
LinkedList.
 element getFirst(): This method returns the first element from the LinkedList.
 element getLast(): This method returns the last element from the LinkedList.
 int indexOf(Object obj); This method returns the position of the first occurrence of the specified
element obj in the list, or -1 if the element is not found in the list.
 int lastIndexOf(Object obj); This method returns the position of the last occurrence of the specified
element obj in the list, or -1 if the element is not found in the list.
 int size(): This method returns the number of elements present in the LinkedList.
 Object[ ] toArray(): This method converts the linked list into an array of Object class type containing
all the elements in the LinkedList in the same sequence.
E.g.: The following program illustrates how to create the LinkedList.
//A LinkedList with strings
import java.io.*;
import java.util.*;
class LLdemo
{
public static void main(String args[])throws IOException
{
//create an empty linked list to store strings
LinkedList<String> ll=new LinkedList<String>();
//add some names to linked list
ll.add("America");
ll.add("India");
ll.add("Japan");
ll.add("India");
//display the elements in the linked list
System.out.println("List= " +ll) ;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String element;
int position, choice=0;
//menu
while(choice<4)
{
System.out.println("\n LINKEDLIST OPERATIONS");
System.out.println("1. Add an element");

29
System.out.println("2. Remove an element");
System.out.println("3. Change an element");
System.out.println("4. Exit");
System.out.print("Enter your choice: ");
choice=Integer.parseInt(br.readLine());
//perform a task depending on user choice
switch(choice)
{
case 1: System.out.print("Enter element: ");
element=br.readLine();
System.out.print("At what position: ") ;
position=Integer.parseInt(br.readLine());
ll.add(position-1, element);
break;
case 2: System.out.print("Enter position: ");
position=Integer.parseInt(br.readLine());
ll.remove(position-1);
break;
case 3: System.out.print("Enter position: ");
position=Integer.parseInt(br.readLine());
System.out.print("Enter new element: ");
element=br.readLine();
ll.set(position-1, element);
break;
default: return;
}
//use Iterator to retrieve the elements
System.out.print("List= ");
Iterator it=ll.iterator();
while(it.hasNext())
System.out.print(it.next()+" ");
ll.addFirst("England");
ll.addLast("Australia");
System.out.println("List= " +ll) ;
ll.removeFirst();
ll.removeLast();
System.out.println("List= " +ll) ;
System.out.println("The element in the position: " +ll.get(2));
System.out.println("The element in the first position: " +ll.getFirst());
System.out.println("The element in the last position: " +ll.getLast());
System.out.println("The size of the list= "+ll.size());
int a=ll.indexOf("India");
int b=ll.lastIndexOf("India");
System.out.println(a);
System.out.println(b);
}

30
}
}
O/P: E:\VBR\JAVA>javac linkedlist.java
E:\VBR\JAVA>java LLdemo
List= [America, India, Japan, India]
LINKEDLIST OPERATIONS
1. Add an element
2. Remove an element
3. Change an element
4. Exit
Enter your choice: 1
Enter element: china
At what position: 1
List= china America India Japan India List= [England, china, America, India, J
an, India, Australia]
List= [china, America, India, Japan, India]
The element in the position: India
The element in the first position: china
The element in the last position: India
The size of the list= 5
2
4
LINKEDLIST OPERATIONS
1. Add an element
2. Remove an element
3. Change an element
4. Exit
Enter your choice: 4
E:\VBR\JAVA>
HashSet class:
A HashSet represents a set of elements (objects). It does not guarantee the order of elements. Also it does not
allow the duplicate elements to be stored. We can write the HashSet class as:
class HashSet<T>
Here, <T> represents the generic type parameter. It represents which type of elements is being stored into the
HashSet. Suppose, we want to create a HashSet to store a group of Strings, then we can create the object as:
HashSet<String> hs=new HashSet<String>();
HashSet class methods:
HashSet class provides the following methods:
 boolean add(element obj): This method adds an element obj to the HashSet. It returns true if the
element is added to the HashSet, else it returns false. If the same element is already available in the
HashSet, then the present element is not added.
 boolean remove(obj): This method removes the element obj from the HashSet, if it is present. It
returns true if the element is removed successfully otherwise false.
 void clear(): This method removes all the elements from the HashSet.
 boolean contains(obj): This returns true if the HashSet contains the specified element obj.
 boolean isEmpty(): This returns true if the HashSet contains no elements.

31
 int size(): This returns the number of elements present in the HashSet.
E.g.: The following program illustrates how to create the HashSet.
import java.util.*;
class HS
{
public static void main(String args[])
{
//create a HashSet to store strings
HashSet<String> hs=new HashSet<String>();
//store some string elements
hs.add("India");
hs.add("America");
hs.add("Japan");
hs.add("China");
hs.add("America");
//view the HashSet
System.out.println("Hash Set = "+ hs);
//add an Iterator to hs
Iterator it=hs.iterator();
//display element by element using Iterator
System.out.println("Elements using Iterator: ");
while(it.hasNext())
{
String s=(String)it.next();
System.out.println(s);
}
}
}
O/P: E:\VBR\JAVA>javac hashset.java
E:\VBR\JAVA>java HS
Hash Set = [America, China, Japan, India]
Elements using Iterator:
America
China
Japan
India

HashMap class methods:


HashMap class includes the following methods:
 value put(key, value): This method stores key – value pair into the HahMap.
 value get(Object key): this method returns the corresponding value when key is given. If the key does
not have a value associated with it, then it returns null.
 Set<k> keyset(): This method, when applied on a HashMap converts it into a Set where only keys
will be stored.
 Collection<v> values(): This method, when applied on a HashMap object returns all the values of the
HashMap into a collection object.

32
 Value remove(Object key): This method removes the key and corresponding value from the
HashMap.
 Void clear(): This method removes all the key – value pairs from the map.
 boolean isEmpty(): This method returns true if there are no key – value pairs in the HashMap.
 int size(): This method returns the number of key – value pairs in the HashMap.
We take a case where we want to create a telephone book using a HashMap. In this book, we store a name of
a person and his telephone number. Since the name is a String and the telephone number is taken as long type
object, we can create a HashMap as:
HashMap<String, Long> hm=new HashMap<String, Long>();
E.g.:
The following program shows the use of HashMap class.
//HashMap used as telephone book
import java.io.*;
import java.util.*;
class HashMapDemo
{
public static void main(String args[])throws IOException
{
//create HashMap
HashMap<String, Long> hm=new HashMap<String, Long>();
//variables
String name,str;
Long phno;
BufferedReader br=new BufferedReader(
new InputStreamReader(System.in));
//menu
while(true)
{
System.out.println("1. Enter phone entries");
System.out.println("2. Lookup in the book");
System.out.println("3. Display names in book");
System.out.println("4. Display phnos in book");
System.out.println("5. Exit");
System.out.print("Enter your choice: ");
int n=Integer.parseInt(br.readLine());
switch(n)
{
case 1: System.out.print("Enter name: ");
name=br.readLine();
System.out.print("Enter phno: ");
str=br.readLine();
phno=new Long(str);
//store name and phno into HashMap
hm.put(name,phno);
break;
case 2: System.out.print("Enter name: ");

33
name=br.readLine();
name=name.trim(); //remove unnecessary spaces
//pass name and get phno
phno=hm.get(name);
System.out.println("phno: " +phno);
break;
case 3: //use keySet() to display the names
//create HashSet object to store names and
//refer it by Set reference
Set<String> set=new HashSet<String>();
set=hm.keySet();
System.out.println(set);
break;
case 4: System.out.println("HashMap size: " +hm.size());
hm.remove("reddy");
System.out.println("HashMap size: " +hm.size());
Collection<Long> c=hm.values();
System.out.println(c);
case 5: return;
}
}
}
}

O/P: F:\JAVA>javac hashmap.java


F:\JAVA>java HashMapDemo
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 1
Enter name: vijay
Enter phno: 8500180366
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 1
Enter name: vbr
Enter phno: 8500920820
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book

34
5. Exit
Enter your choice: 2
Enter name: vijay
phno: 8500180366
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 3
[vbr, vijay]
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 4
HashMap size: 2
HashMap size: 2
[8500920820, 8500180366]

TreeMap:
TreeMap implements NavigableMap interface. TreeMap can be used to store a group of objects as key –
value pairs where all the elements are arranged according to some sorting order of keys. Duplicate keys are
not allowed but values can be duplicated. Insertion order is not allowed because insertion is based on some
sorting order of keys. The difference between HashMap and TreeMap is, HashMap can contain one null key.
TreeMap cannot contain any null key. Another difference is, HashMap maintains no order. But TreeMap
maintains ascending order.
E.g.:
//TreeMap used as telephone book
import java.io.*;
import java.util.*;
class TreeMapDemo
{
public static void main(String args[])throws IOException
{
//create TreeMap
TreeMap<String, Long> tm=new TreeMap<String, Long>();

//variables
String name,str;
Long phno;
BufferedReader br=new BufferedReader(
new InputStreamReader(System.in));

//menu

35
while(true)
{
System.out.println("1. Enter phone entries");
System.out.println("2. Lookup in the book");
System.out.println("3. Display names in book");
System.out.println("4. Display phnos in book");
System.out.println("5. Exit");

System.out.print("Enter your choice: ");


int n=Integer.parseInt(br.readLine());

switch(n)
{
case 1: System.out.print("Enter name: ");
name=br.readLine();
System.out.print("Enter phno: ");
str=br.readLine();
phno=new Long(str);
//store name and phno into HashMap
tm.put(name,phno);
break;
case 2: System.out.print("Enter name: ");
name=br.readLine();
name=name.trim(); //remove unnecessary spaces
//pass name and get phno
phno=tm.get(name);
System.out.println("phno: " +phno);
break;
case 3: //use keySet() to display the names
//create HashSet object to store names and
//refer it by Set reference
Set<String> set=new HashSet<String>();
set=tm.keySet();
System.out.println(set);
break;
case 4: System.out.println("TreeMap size: " +tm.size());
tm.remove("reddy");
System.out.println("TreeMap size: " +tm.size());
Collection<Long> c=tm.values();
System.out.println(c);
case 5: return;
}
}
}
}

36
O/P: F:\JAVA>javac treemap.java

F:\JAVA>java TreeMapDemo
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 1
Enter name: vijay
Enter phno: 8500180366
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 1
Enter name: anil
Enter phno: 9885411869
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 1
Enter name: sunil
Enter phno: 9490966840
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 3
[anil, sunil, vijay]
1. Enter phone entries
2. Lookup in the book
3. Display names in book
4. Display phnos in book
5. Exit
Enter your choice: 4
TreeMap size: 3
TreeMap size: 3
[9885411869, 9490966840, 8500180366]

37

You might also like