package ose111;
import [Link].*;
public class StudentAttendance {
public static void main(String[] args) {
Scanner scanner = new Scanner([Link]);
// HashMap to store attendance records using Student ID as key
HashMap<String, String> attendance = new HashMap<>();
// Read number of students
int n = [Link]([Link]().trim());
// Read student attendance records
for (int i = 0; i < n; i++) {
String input = [Link]().trim();
String[] parts = [Link](" ");
String studentID = parts[0];
String status = parts[1];
[Link](studentID, status);
// Read number of operations
int m = [Link]([Link]().trim());
// Store all output results
List<String> results = new ArrayList<>();
// Process operations
for (int i = 0; i < m; i++) {
String[] command = [Link]().trim().split(" ");
String operation = command[0];
switch (operation) {
case "GET":
String getStudentID = command[1];
if ([Link](getStudentID)) {
[Link]([Link](getStudentID));
} else {
[Link]("Not Found");
break;
case "CHECK_KEY":
String checkKeyStudentID = command[1];
if ([Link](checkKeyStudentID)) {
[Link]("Yes");
} else {
[Link]("No");
break;
case "CHECK_VALUE":
String checkValueStatus = command[1];
if ([Link](checkValueStatus)) {
[Link]("Yes");
} else {
[Link]("No");
break;
case "REPLACE":
String replaceStudentID = command[1];
String newStatus = command[2];
if ([Link](replaceStudentID)) {
[Link](replaceStudentID, newStatus);
[Link]("Updated");
} else {
[Link]("Not Found");
break;
// Output all results
for (String result : results) {
[Link](result);
[Link]();
}
DISCUSS PURPOSE OF MAIN() THREAD IN JAVA AND ITS INTERACTION WITH OTHER THREADS WITH
EG
Purpose of main() Thread in Java
In Java, every program starts its execution from the main() method, and this method is run by a
special thread called the main thread. It is the first thread that gets created when a Java program
starts, and it plays a key role in the life cycle of other threads.
Key Roles of main() Thread
1. Program Entry Point: The main() method is the starting point of the application.
2. Thread Creator: It often creates and starts other threads (e.g., worker threads, background
tasks).
3. Controls Flow: It can wait for other threads to complete using join().
4. Can Run Concurrently: The main() thread runs concurrently with other threads it spawns.
Interaction Between main() and Other Threads
The main() thread and other threads can:
Run simultaneously (concurrently).
Communicate via shared objects.
Coordinate execution using thread methods like join(), sleep(), wait(), notify().
class MyThread extends Thread {
public void run() {
for(int i = 1; i <= 5; i++) {
[Link]("Child Thread: " + i);
try { [Link](500); } catch (InterruptedException e) {}
public class MainThreadDemo {
public static void main(String[] args) {
MyThread t = new MyThread(); // Create a new thread
[Link](); // Start the child thread
for(int i = 1; i <= 5; i++) {
[Link]("Main Thread: " + i);
try { [Link](500); } catch (InterruptedException e) {}
Q) PROD CONSUMER
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
while (!valueSet) {
try { wait(); } catch (InterruptedException e) {}
[Link]("Got: " + n);
valueSet = false;
notify();
return n;
synchronized void put(int n) {
while (valueSet) {
try { wait(); } catch (InterruptedException e) {}
this.n = n;
valueSet = true;
if (n <= 5) {
[Link]("Put: " + n);
notify();
class Producer extends Thread {
Q q;
Producer(Q q) { this.q = q; start(); }
public void run() {
int i = 1;
while (i <= 5) [Link](i++);
class Consumer extends Thread {
Q q;
Consumer(Q q) { this.q = q; start(); }
public void run() {
for (int i = 1; i <= 5; i++) [Link]();
public class ProducerConsumer {
public static void main(String[] args) {
Q q = new Q();
new Producer(q);
new Consumer(q);
}
Q- JUSTIFY THE USE OF JOIN () METHOD IN CONTRIBUTING TO THE CONTROL FLOW IN
MULTITHREADED APPLN
The join() method in Java pauses the current thread (usually the main thread) until another thread
finishes execution.
[Link](); // main thread waits until 'thread' completes
Why is join() Important in Multithreading?
1. Maintains Proper Execution Order
When threads are running in parallel, their execution order becomes unpredictable. join() ensures
one thread finishes completely before another continues, enabling deterministic control flow.
🔍 Example Use Case: Waiting for a file download thread to finish before starting file processing.
2. Avoids Race Conditions and Incomplete Results
Without join(), the main thread might continue before the background threads complete their tasks,
leading to incomplete or incorrect results.
🔍 Example: Summing values using a thread, and printing the total in the main thread — without
join(), the total may be printed before the thread finishes computing.
3. Makes Synchronization Simpler
Instead of using complex synchronization mechanisms, sometimes join() is all you need to wait for
one or more threads to complete before proceeding.
class Worker extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
[Link]("Worker thread: " + i);
public class JoinExample {
public static void main(String[] args) throws InterruptedException {
Worker w = new Worker();
[Link]();
// Main thread waits until Worker thread completes
[Link]();
[Link]("Main thread continues after Worker finishes");
Q- ILLUSTRATE THE WORKING MODEL AND METHODS ASSOSCIATED WITH STACK AND DEQUEUE
COLLECTION IN JAVA WITH EG
What is a Stack?
A Last-In-First-Out (LIFO) data structure.
Think of a stack of plates — the last plate you put on top is the first one you take off.
Common Methods:
Method Description
push(E item) Adds item to top
pop() Removes and returns top element
peek() Returns top element without removing
empty() Checks if stack is empty
search(Object o) Returns position (1-based) from top
import [Link];
public class StackExample {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
[Link]("A");
[Link]("B");
[Link]("C");
[Link]("Top: " + [Link]()); // C
[Link]("Removed: " + [Link]()); // C
[Link]("Now Top: " + [Link]()); // B
[Link]("Position of A: " + [Link]("A")); // 2
[Link]("Is Empty? " + [Link]()); // false
Q - USE ARRAYLIST COLLECTION IN JAVA WITH EG
What is ArrayList?
ArrayList is a resizable array in Java, part of the [Link] package.
It allows dynamic addition/removal of elements (unlike arrays which are fixed size).
It maintains insertion order.
Can contain duplicate elements.
Indexed access (like arrays).
Commonly Used Methods
Method Description
add(E e) Adds element to the end
Adds element at specified
add(int index, E e)
index
get(int index) Returns element at index
set(int index, E e) Replaces element at index
remove(int index) Removes element at index
Returns number of
size()
elements
contains(Object o) Checks if element exists
isEmpty() Checks if list is empty
clear() Removes all elements
import [Link];
Method Description
public class ArrayListExample {
public static void main(String[] args) {
// Create an ArrayList of strings
ArrayList<String> fruits = new ArrayList<>();
// Adding elements
[Link]("Apple");
[Link]("Banana");
[Link]("Mango");
[Link]("Apple"); // Duplicates allowed
// Accessing elements
[Link]("First fruit: " + [Link](0)); // Apple
// Changing element
[Link](1, "Orange");
// Removing element
[Link](2); // Removes "Mango"
// Size of list
[Link]("Total fruits: " + [Link]());
// Check if contains
[Link]("Contains Banana? " +
[Link]("Banana")); // false
// Print all fruits
[Link]("All Fruits:");
for (String fruit : fruits) {
Method Description
[Link](fruit);
Q- EXPLAIN THE HIERARCHY OF COLLECTION INTERFACE AND CLASSES
Java Collection Framework Hierarchy
The Java Collection Framework provides standard data structures (like lists, sets, queues, maps) and
algorithms to operate on them.
It is mainly divided into three parts:
1. Collection Interface (Root of List, Set, Queue)
2. Map Interface (Separate from Collection)
3. Iterator & ListIterator (for traversing collections)
[Link] (Interface)
|-- [Link] (Interface)
| |-- ArrayList
| |-- LinkedList
| |-- Vector
| |-- Stack
|-- [Link] (Interface)
| |-- HashSet
| |-- LinkedHashSet
| |-- TreeSet
|-- [Link] (Interface)
|-- PriorityQueue
|-- ArrayDeque
Q- ILLUSTRATE THE LIFE CYCLE OF THREAD WITH EG
Life Cycle of a Thread in Java
A thread in Java goes through the following 5 states:
1. New
2. Runnable
3. Running
4. Blocked/Waiting (Non-Runnable)
5. Terminated (Dead)
EG:
class MyThread extends Thread {
public void run() {
try {
[Link]("Thread is running...");
[Link](1000); // Thread goes to BLOCKED state
} catch (InterruptedException e) {
[Link]("Thread interrupted");
[Link]("Thread has finished.");
public class ThreadLifeCycle {
public static void main(String[] args) {
MyThread t = new MyThread(); // NEW state
[Link]("Thread created: NEW");
[Link](); // RUNNABLE state
[Link]("Thread started: RUNNABLE");
try {
[Link](); // Main thread waits for t to finish
} catch (InterruptedException e) {
[Link]("Main thread interrupted");
[Link]("Main thread ends: t is TERMINATED");
Q- METHODS OF THREAD CLASS EG PROGRAM
Key Thread methods covered:
start()
run()
sleep()
setName()
getName()
getId()
getPriority()
setPriority()
isAlive()
join()
yield()
interrupt()
isInterrupted()
class MyThread extends Thread {
public MyThread(String name) {
super(name); // Set thread name
public void run() {
[Link](getName() + " started running.");
for (int i = 1; i <= 5; i++) {
[Link](getName() + " is working, count: " + i);
if (i == 3) {
[Link](getName() + " is yielding control...");
[Link](); // Hint to scheduler to switch thread (though only one thread here)
try {
[Link](500); // Sleep for 500ms (simulate work)
} catch (InterruptedException e) {
[Link](getName() + " got interrupted!");
return; // Stop running if interrupted
[Link](getName() + " finished running.");
public class ThreadMethodsDemo {
public static void main(String[] args) {
MyThread t1 = new MyThread("Worker-1");
[Link]("Thread ID before start: " + [Link]());
[Link]("Thread Name before start: " + [Link]());
[Link]("Thread Priority before start: " + [Link]());
[Link]("Is thread alive? " + [Link]());
// Change priority before starting
[Link](Thread.MAX_PRIORITY);
[Link](); // Start the thread
[Link]("Thread started.");
[Link]("Is thread alive now? " + [Link]());
try {
// Main thread waits for t1 to finish
[Link]();
} catch (InterruptedException e) {
[Link]("Main thread interrupted while waiting.");
[Link]("Is thread alive after join? " + [Link]());
// Interrupt the thread after it's done to show interrupt effect (won't do anything)
[Link]();
[Link]("Is thread interrupted? " + [Link]());
[Link]("Main thread ends.");
}
[Link]<E>
-----------------------
| |
Collection<E> Map<K,V> (not a subtype of Collection)
------------------------------
| | |
List<E> Set<E> Queue<E>
| | |
ArrayList HashSet LinkedList
LinkedList TreeSet PriorityQueue
Vector LinkedHashSet
Stack EnumSet
What are Collections?
Collections in Java are data structures that store and manage groups of objects (called elements) in
a flexible and efficient way.
Instead of managing individual objects one by one, collections help you store, retrieve,
manipulate, and iterate over groups of objects.
They are part of the Java Collection Framework which provides ready-to-use classes and
interfaces to work with data collections.
Why use Collections?
To store multiple objects together (like lists of names, sets of unique IDs, queues for tasks).
To easily perform common operations such as adding, removing, searching, sorting, and
iterating over elements.
To improve code reusability and readability by using standard data structures instead of
writing your own.
Types of Collections
Some common collection types you will often use:
Collection Type Description Example Classes
List Ordered collection, allows duplicates ArrayList, LinkedList
Set No duplicate elements HashSet, TreeSet
Queue Elements processed in order (FIFO or priority) LinkedList, PriorityQueue
Q JUSTIFY THE USE OF SYNCHRONIZATION BLOCKS OR METHODS EG
Why Use Synchronization?
When multiple threads access and modify shared resources (like variables, objects) at the
same time, it can cause data inconsistency or unexpected behavior.
Synchronization ensures that only one thread at a time can access a critical section of code
or resource.
This prevents race conditions and makes your program thread-safe.
What is a Synchronization Block or Method?
A synchronized method locks the entire method so only one thread can execute it at once.
A synchronized block locks a specific part of code on a given object, allowing finer control.
Simple Example: Bank Account Withdrawal
Imagine multiple threads trying to withdraw money from the same bank account at the same time.
Without synchronization, the balance could become incorrect.
class BankAccount {
private int balance = 100;
// Synchronize the withdraw method
public synchronized void withdraw(int amount) {
if (balance >= amount) {
[Link]([Link]().getName() + " is withdrawing " + amount);
balance = balance - amount;
[Link]([Link]().getName() + " new balance: " + balance);
} else {
[Link]([Link]().getName() + " Insufficient balance");
public int getBalance() {
return balance;
public class SyncDemo {
public static void main(String[] args) {
BankAccount account = new BankAccount();
Runnable task = () -> {
[Link](75);
};
Thread t1 = new Thread(task, "Thread-1");
Thread t2 = new Thread(task, "Thread-2");
[Link]();
[Link]();
Q GENERICS WITH EASY SMALL EG
What are Generics?
Generics let you create classes, methods, or interfaces that work with any data type while
providing type safety.
They help you avoid casting and ClassCastException by ensuring the type correctness at
compile time.
You write a single class or method that can work with different data types.
// Generic class with type parameter T
class Box<T> {
private T item;
public void setItem(T item) {
[Link] = item;
public T getItem() {
return item;
public class GenericsDemo {
public static void main(String[] args) {
// Box to hold Integer
Box<Integer> intBox = new Box<>();
[Link](123);
[Link]("Integer value: " + [Link]());
// Box to hold String
Box<String> strBox = new Box<>();
[Link]("Hello Generics");
[Link]("String value: " + [Link]());
What happens here?
Box<T> is a generic class where T is a placeholder for any type.
When creating objects, you specify the type inside <>.
This way, you can have a box for Integer, String, or any other object, all using the same
class.
Why use generics?
Type safety: No need to cast objects.
Code reuse: One class/method can work with multiple types.
Cleaner code: Avoids runtime errors due to wrong types.
M3
Method What it Does Returns Example Use Case
.charAt(int) Get char at index char Access single character
.getChars(...) Copy substring chars to array void Bulk copy substring into char[]
.getBytes() Get bytes of the string byte[] Encoding/decoding operations
.toCharArray() Convert whole string to char[] char[] Iterate/manipulate chars
String str = "Hello, World!";
char[] dest = new char[5];
[Link](7, 12, dest, 0); // Copies 'World' to dest starting at index 0
[Link](dest); // Output: World
String str = "Hello";
byte[] bytes = [Link]();
for (byte b : bytes) {
[Link](b + " "); // Outputs ASCII values: 72 101 108 108 111
String str = "Hello";
char[] chars = [Link]();
for (char c : chars) {
[Link](c + " "); // Output: H e l l o
}
Constructor Description
Creates an empty StringBuffer with
StringBuffer()
default capacity (16 chars).
Creates an empty StringBuffer with
StringBuffer(int capacity)
specified initial capacity.
Creates a StringBuffer initialized
StringBuffer(String str) with the contents of the given
string.
1. StringBuffer()
Creates an empty buffer with an initial capacity of 16
characters.
StringBuffer sb = new StringBuffer();
[Link]("Capacity: " + [Link]()); // Output: 16
2. StringBuffer(int capacity)
Creates an empty buffer with a specified capacity.
StringBuffer sb = new StringBuffer(50);
[Link]("Capacity: " + [Link]()); // Output: 50
3. StringBuffer(String str)
Creates a buffer initialized to the content of the given string.
The capacity will be the string length + 16.
StringBuffer sb = new StringBuffer("Hello");
[Link]([Link]()); // Output: Hello
[Link]([Link]()); // Output: 21 (5 + 16)
STRING BUFFER CONSTRUCTORS