_Core Java & Collections Framework
_Core Java & Collections Framework
Java Introductions:
1. What is Java?
Java is a high-level, object-oriented, platform-independent programming language
developed by Sun Microsystems (now owned by Oracle) in 1995. It follows the "Write
Once, Run Anywhere" (WORA) principle, meaning compiled Java code can run on any
device with a Java Virtual Machine (JVM).
1. Android Applications
2. Web Applications
● Java frameworks like Spring Boot and Jakarta EE are used for scalable web apps.
● Example: LinkedIn, Amazon (backend services).
● Hadoop, Apache Spark, and Flink use Java for distributed computing.
● Example: Data processing in Netflix, eBay.
5. Enterprise Software
8. Gaming
Conclusion
Java remains one of the most popular programming languages due to its portability,
security, and scalability. It is used in web, mobile, enterprise, and embedded systems,
making it a versatile choice for developers.
4. Application Flow Diagram
Topics Summary:
Numeric Types
● byte
○ Size: 8-bit (1 byte)
○ Range: -128 to 127
○ Default: 0
○ Example: byte fileSize = 120;
● short
○ Size: 16-bit (2 bytes)
○ Range: -32,768 to 32,767
○ Default: 0
○ Example: short temperature = -200;
● int
○ Size: 32-bit (4 bytes)
○ Range: -2³¹ to 2³¹-1
○ Default: 0
○ Example: int population = 2147483647;
● long
○ Size: 64-bit (8 bytes)
○ Range: -2⁶³ to 2⁶³-1
○ Default: 0L
○ Example: long globalPopulation = 7900000000L;
● float
○ Size: 32-bit (4 bytes)
○ Range: ±1.4E-45 to ±3.4E+38
○ Default: 0.0f
○ Example: float piApprox = 3.14159f;
● double
○ Size: 64-bit (8 bytes)
○ Range: ±4.9E-324 to ±1.7E+308
○ Default: 0.0d
○ Example: double precisePi = 3.141592653589793;
Non-Numeric Types
● char
○ Size: 16-bit (2 bytes)
○ Range: '\u0000' to '\uffff' (0 to 65,535)
○ Default: '\u0000'
○ Example: char grade = 'A';
● boolean
○ Size: Not precisely defined (typically 1 bit)
○ Range: true or false
○ Default: false
○ Example: boolean isJavaFun = true;
Autoboxing/Unboxing Examples:
java
// Autoboxing (primitive → wrapper)
Integer autoBoxed = 42; // Compiler does Integer.valueOf(42)
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
boolean false
● Primitive Types:
○ byte, boolean: 1 byte (boolean size JVM-dependent)
○ short, char: 2 bytes
○ int, float: 4 bytes
○ long, double: 8 bytes
● Wrapper Objects:
○ Typically consume more memory due to object overhead (header + fields)
○ Example: Integer object requires ~16 bytes (12 object header + 4 for int
value)
Memory Locations:
● Primitive Types:
○ Local variables: Stack memory
○ Instance variables: Inside object on heap
○ Array elements: Contiguous memory (heap for object arrays)
● Wrapper Objects:
○ Always allocated on heap
○ References stored in stack (for local vars) or heap (for instance vars)
void method() {
int localPrimitive = 10; // 4 bytes on stack
Integer localWrapper = 20; // Reference on stack, object on heap
}
}
Autoboxing Example:
java
int primitiveInt = 42;
Integer wrapperInt = primitiveInt; // Autoboxing (int → Integer)
System.out.println(wrapperInt); // Output: 42
Unboxing Example:
java
Integer wrapperInt = 100;
int primitiveInt = wrapperInt; // Unboxing (Integer → int)
System.out.println(primitiveInt); // Output: 100
Use in Collections:
java
List<Integer> numbers = new ArrayList<>();
numbers.add(5); // Autoboxing (int → Integer)
int num = numbers.get(0); // Unboxing (Integer → int)
Definition:
Type casting is the process of converting one data type into another. Java supports two
types of casting:
1. Implicit (Widening) Casting – Automatically done by the compiler (smaller → larger
type).
2. Explicit (Narrowing) Casting – Requires manual intervention (larger → smaller
type).
ASCII codes for uppercase (A-Z) and lowercase (a-z) letters in Java:
package Demo;
public class Main {
public static void main(String[] args) {
byte b = 65;
System.out.println(b);
b = (byte) 129;
System.out.println(b);
}
}
package Demo;
public class Main {
public static void main(String[] args) {
byte b = 65;
short s = b;
System.out.println(s);
long l = b;
System.out.println(l);
char c = 'A';
System.out.println(c);
}
}
Total =>23
=============================
package Demo;
public class Main {
public static void main(String[] args) {
int b = 65;
char c = (char) b;
System.out.println(c);
short s = (short) b;
System.out.println(s);
}
}
Operations on data:
1) (byte, short, int, char) + (byte, short, int, char) => int
2) (byte, short, int, long, char) + long => long
3) (byte, short, int, long, float, char) + float => float
4) (byte, short, int, long, float, double, char) + double => double
package Demo;
public class Main {
public static void main(String[] args) {
int a = 10;
Integer b = a; // Auto converts int to Integer (autoboxing)
System.out.println(b);
double d = 9.99;
Double e = d; // Auto converts double to Double
System.out.println(e);
boolean flag = true;
Boolean f = flag; // Auto converts boolean to Boolean
System.out.println(f);
}
}
package Demo;
public class Main {
public static void main(String[] args) {
Integer b = 10; // Integer object
int a = b; // Auto converts Integer to int (auto-unboxing)
System.out.println(a);
Double e = 9.99; // Double object
double d = e; // Auto converts Double to double
System.out.println(d);
1. Arithmetic Operators
Example:
java
int a = 10, b = 3;
System.out.println(a + b); // 13
System.out.println(a % b); // 1 (remainder)
System.out.println(++a); // 11 (pre-increment)
2. Relational Operators
== Equal to if (a ==
b)
!= Not equal to if (a !=
b)
Example:
java
int x = 5, y = 10;
System.out.println(x == y); // false
System.out.println(x < y); // true
3. Logical Operators
|| Logical OR if (a > 0 || b
> 0)
Example:
java
boolean isTrue = true, isFalse = false;
System.out.println(isTrue && isFalse); // false
System.out.println(isTrue || isFalse); // true
System.out.println(!isTrue); // false
4. Assignment Operators
Used to assign values to variables.
Example:
java
int num = 10;
num += 5; // num = 15
num %= 3; // num = 0
5. Bitwise Operators
| Bitwise OR a | b
^ Bitwise XOR a ^ b
Example:
java
int x = 5; // Binary: 0101
int y = 3; // Binary: 0011
System.out.println(x & y); // 1 (0001)
System.out.println(x << 1); // 10 (1010)
6. Ternary Operator
Example:
java
int a = 10, b = 20;
int max = (a > b) ? a : b; // max = 20
7. instanceof Operator
Example:
java
String str = "Hello";
System.out.println(str instanceof String); // true
1.9 Java Statements
Statements in Java are complete instructions that perform actions. They can
include declarations, expressions, and control flow structures. Below is a
detailed breakdown of different types of statements in Java with examples.
1. Expression Statements
Examples:
java
int a = 10; // Assignment statement
a++; // Increment statement
System.out.println(a); // Method call statement
2. Declaration Statements
Examples:
java
int age = 25; // Variable declaration & initialization
String name = "Alice"; // String variable
final double PI = 3.14; // Constant declaration
A. Conditional Statements
1. if Statement
java
int num = 10;
if (num > 0) {
System.out.println("Positive number");
}
2. if-else Statement
java
int age = 17;
if (age >= 18) {
System.out.println("Adult");
} else {
System.out.println("Minor");
}
3. if-else-if Ladder
java
int marks = 85;
if (marks >= 90) {
System.out.println("Grade A");
} else if (marks >= 80) {
System.out.println("Grade B");
} else {
System.out.println("Grade C");
}
4. switch Statement
java
int day = 3;
switch (day) {
case 1: System.out.println("Monday"); break;
case 2: System.out.println("Tuesday"); break;
case 3: System.out.println("Wednesday"); break;
default: System.out.println("Invalid day");
}
B. Looping Statements
1. for Loop
java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
2. while Loop
java
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
3. do-while Loop
java
int i = 0;
do {
System.out.println(i);
i++;
} while (i < 5);
java
int[] numbers = {1, 2, 3, 4};
for (int num : numbers) {
System.out.println(num);
}
C. Jump Statements
1. break Statement
java
for (int i = 0; i < 10; i++) {
if (i == 5) break; // Stops at 5
System.out.println(i);
}
2. continue Statement
java
for (int i = 0; i < 5; i++) {
if (i == 2) continue; // Skips 2
System.out.println(i);
}
3. return Statement
Exits a method and optionally returns a value.
java
int add(int a, int b) {
return a + b;
}
A. try-catch Block
java
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
}
B. try-catch-finally Block
java
try {
int[] arr = new int[3];
arr[5] = 10; // Throws ArrayIndexOutOfBoundsException
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
} finally {
System.out.println("This always executes.");
}
C. throw Statement
java
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative!");
}
D. throws Keyword
Declares exceptions a method might throw.
java
void readFile() throws IOException {
// Code that may throw IOException
}
5. Synchronization Statements
synchronized Block
java
synchronized (this) {
// Thread-safe code
}
6. Assertion Statements
java
int value = 15;
assert value > 10 : "Value must be greater than 10";
void drive() {
System.out.println("Car is driving");
}
void stop() {
System.out.println("Car is stopped");
}
}
myCar.drive();
myCar.stop();
}
}
A class is a blueprint or template that defines the structure and behavior (via fields and
methods) that the objects created from the class will have.
Syntax
class ClassName {
// fields
// methods
}
Example
public class Employee {
int id;
String name;
void displayInfo() {
System.out.println("ID: " + id + ", Name: " + name);
}
}
Example
package Demo;
// POJO Class Example
public class Person {
int id;
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package Demo;
public class Test {
public void display(Person p) {
System.out.println(p.getId()+" "+p.getName());
p.setId(2);
p.setName("Ramesh");
}
}
package Demo;
public class Main {
public static void main(String[] args) {
Person p = new Person();
p.setId(1);
p.setName("Maqbool");
Test t = new Test();
t.display(p);
System.out.println(p.getId()+" "+p.getName());
}
}
It is used to:
🔧 Syntax of a Method:
returnType methodName(parameter1, parameter2, ...) {
// method body
return value; // (if not void)
}
1 Instance Methods
● Belong to an object of a class
● Require object creation to be called
● Can access instance variables and other instance methods
package Demo;
}
public String test() {
return str;
System.out.println(str);
System.out.println(s);
System.out.println(s);
return str;
package Demo;
d.display();
System.out.println(msg);
d.show("Hello World");
String showMsg = d.getShow("Hello World");
System.out.println(showMsg);
java
class Calculator {
// Instance method
public int add(int a, int b) {
return a + b;
}
}
2 Static Methods
● Belong to the class rather than any object
● Can be called without object instantiation
● Can only access static variables and other static methods
java
class MathOperations {
// Static method
public static int multiply(int a, int b) {
return a * b;
}
}
public class Main {
public static void main(String[] args) {
int product = MathOperations.multiply(4, 5); // Calling static method
System.out.println(product); // Output: 20
}
}
package Demo;
public class Demo {
package Demo;
public class Test {
public static void main(String[] args) {
Demo.display();
String msg = Demo.test();
System.out.println(msg);
Demo.show("Hello World");
String showMsg = Demo.getShow("Hello World");
System.out.println(showMsg);
}
}
3 Abstract Methods
java
abstract class Shape {
// Abstract method
public abstract double calculateArea();
}
public Circle(double r) {
this.radius = r;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
4 Factory Methods
java
class Logger {
private Logger() {} // Private constructor
// Factory method
public static Logger getLogger() {
return new Logger();
}
5 Synchronized Methods
java
class Counter {
private int count = 0;
// Synchronized method
public synchronized void increment() {
count++;
}
package Demo;
public class Test {
public static void main(String[] args) {
Demo d = new Demo();
d.display();
String msg = d.test();
d.show("Hello World");
String showMsg = d.getShow("Hello World");
}
}
package Demo;
public class Demo {
public static void display() {
System.out.println("Without Parameter Without Return Type
called..");
}
public static String test() {
String str = "Without Parameter With Return Type Called..";
return str;
}
public static void show(String s) {
String str = "With Parameter Without Return Type Called..";
System.out.println(str);
System.out.println(s);
}
public static String getShow(String s) {
String str = "With Parameter With Return Type Called..";
System.out.println(str);
System.out.println(s);
return str;
}
}
package Demo;
public class Test {
public static void main(String[] args) {
Demo.display();
String msg = Demo.test();
Demo.show("Hello World");
String showMsg = Demo.getShow("Hello World");
}
}
1 Direct Invocation
The most common way to call a method by its name with appropriate arguments.
java
class Greeter {
public void greet(String name) {
System.out.println("Hello, " + name);
}
}
2 Method Chaining
java
class StringBuilderExample {
private StringBuilder sb = new StringBuilder();
3 Recursive Calls
java
class Factorial {
public static int calculate(int n) {
if (n <= 1) return 1;
return n * calculate(n - 1); // Recursive call
}
}
4 Callback Methods
java
interface Callback {
void execute();
}
class Task {
public void performTask(Callback callback) {
System.out.println("Performing task...");
callback.execute();
}
}
5 Method References
6 Reflection API
java
import java.lang.reflect.Method;
class ReflectionExample {
public void showMessage(String msg) {
System.out.println("Message: " + msg);
}
}
// Instance Method
void showInstance() {
System.out.println("Instance x: " + x);
System.out.println("Static y: " + y);
}
// Static Method
❌
static void showStatic() {
// System.out.println(x); Error: Cannot access instance variable directly
System.out.println("Static y: " + y);
}
}
✅
Example obj = new Example();
✅
obj.showInstance(); // Instance method
Example.showStatic(); // Static method
}
}
✅ Syntax:
class Student {
String name;
int age;
// Constructor
Student(String n, int a) {
name = n;
age = a;
}
}
● Takes no parameters.
class Student {
String name;
int age;
class Student {
String name;
int age;
class Student {
String name;
int age;
Student(String n, int a) {
name = n;
age = a;
}
// Copy constructor
Student(Student s) {
name = s.name;
age = s.age;
}
}
this keyword:
package Demo;
public class Main {
public static void main(String[] args) {
Car c = new Car();
c.setId(1);
c.setName("BMW");
// Car c = new Car();
// c.setId(11);
// c.setName("Car Engine");
c.getCarDetails();
c.getEngineDetails();
}
}
package Demo;
public class Car extends Engine{
public int id;
public String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void getCarDetails() {
System.out.println("getCarDetails: "+this.id+" "+this.name);
}
}
super keyword:
package Demo;
public class Car extends Engine{
public int id;
public String name;
public void setId(int id) {
super.id = id;
}
public void setName(String name) {
super.name = name;
}
public void getCarDetails() {
System.out.println("getCarDetails: "+this.id+" "+this.name);
}
}
this()
package Demo;
public class Main {
public static void main(String[] args) {
Bike b = new Bike(2,"Kawasaki");
// Bike b = new Bike(22,"Bike Engine");
b.getBikeDetails();
b.getEngineDetails();
}
}
package Demo;
public class Bike extends Engine{
public int id;
public String name;
public Bike() {
System.out.println(" Bike() costructor called..");
}
public Bike(int id, String name) {
this();
this.id = id;
this.name = name;
}
public void getBikeDetails() {
System.out.println("getBikeDetails: "+this.id+" "+this.name);
}
}
package Demo;
public class Engine {
public int id;
public String name;
public Engine() {
}
public Engine(int id, String name) {
this.id=id;
this.name = name;
}
public void getEngineDetails(){
System.out.println("getEngineDetails: "+this.id+" "+this.name);
}
}
super()
● Calls the constructor of the parent class.
package Demo;
public class Main {
public static void main(String[] args) {
// Bike b = new Bike(2,"Kawasaki");
Bike b = new Bike(22,"Bike Engine");
b.getBikeDetails();
b.getEngineDetails();
}
}
package Demo;
public class Bike extends Engine{
public int id;
public String name;
public Bike() {
System.out.println(" Bike() costructor called..");
}
public Bike(int id, String name) {
super(id,name);
// this.id = id;
// this.name = name;
}
public void getBikeDetails() {
System.out.println("getBikeDetails: "+this.id+" "+this.name);
}
}
package Demo;
public class Engine {
public int id;
public String name;
public Engine() {
}
public Engine(int id, String name) {
this.id=id;
this.name = name;
}
public void getEngineDetails(){
System.out.println("getEngineDetails: "+this.id+" "+this.name);
}
}
1. Pre/Post
package Demo;
public class Main {
public static void main(String[] args) {
int a = 5;
//Pre Increment
// System.out.println(++a);
//Post Increment
// System.out.println(a++);
// System.out.println(a);
//Pre deccrement
// System.out.println(--a);
// Post deccrement
System.out.println(a--);
System.out.println(a);
}
}
2. Difference between special operators shortcuts for sum,
multi,..?
package Demo;
public class Main {
public static void main(String[] args) {
int a =5;
int b =10;
// a = a+b; //a=5+10
a+=b;
System.out.println(a);
}
}
4.1. Inheritance
Definition:
Inheritance is a mechanism where a child class acquires the properties (fields) and
behaviors (methods) of a parent class. It promotes code reusability.
Types of Inheritance:
class Animal {
void eat() {
System.out.println("Eating...");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Barking...");
}
}
class Animal {
void eat() { System.out.println("Eating..."); }
}
class Dog extends Animal {
void bark() { System.out.println("Barking..."); }
}
class Puppy extends Dog {
void weep() { System.out.println("Weeping..."); }
}
3 Hierarchical Inheritance – Multiple subclasses inherit from a single superclass.
java
class Animal {
void eat() { System.out.println("Eating..."); }
}
class Dog extends Animal {
void bark() { System.out.println("Barking..."); }
}
class Cat extends Animal {
void meow() { System.out.println("Meowing..."); }
}
4 Multiple Inheritance (Achieved via Interfaces) – A class implements multiple interfaces.
java
interface A { void showA(); }
interface B { void showB(); }
class C implements A, B {
public void showA() { System.out.println("A"); }
public void showB() { System.out.println("B"); }
}
5 Hybrid Inheritance – Combination of two or more inheritance types (Java uses interfaces
to achieve this).
Types of Polymorphism:
class Animal {
void sound() { System.out.println("Animal sound"); }
}
class Dog extends Animal {
@Override
void sound() { System.out.println("Bark"); }
1. }
1 Method Overloading:
package Demo;
public class Calculator {
// Method to add two integers
int add(int a, int b) {
return a + b;
}
package Demo;
public class Main {
public static void main(String[] args) {
Calculator c = new Calculator();
class Calculator {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
}
java
class Animal {
void sound() { System.out.println("Animal sound"); }
}
class Dog extends Animal {
@Override
void sound() { System.out.println("Bark"); }
}
2 Method Overriding:
package Demo;
public class Main {
public static void main(String[] args) {
// Same type (Engine) but different behaviors
Engine engine1 = new Car(); // Car engine - Up casting
Engine engine2 = new Bike(); // Bike engine - Up casting
engine1.start(); // Output: "Vroom! Car engine starts"
engine2.start(); // Output: "Put-put! Bike engine starts"
}
}
package Demo;
public class Bike extends Engine{
public void start() {
System.out.println("Put-put! Bike engine starts");
}
}
package Demo;
public class Car extends Engine{
public void start() {
System.out.println("Vroom! Car engine starts");
}
}
package Demo;
public class Engine {
public void start() {
System.out.println("Engine start called...");
}
}
4.3. Abstraction
Abstraction hides complex implementation details and shows only essential features.
4.4. Encapsulation
Encapsulation binds data (variables) and methods into a single unit and restricts
direct access.
Example:
java
class Student {
private String name; // Private field
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String name) {
this.name = name;
}
}
Key Features:
java
interface Vehicle {
System.out.println("Car started.");
System.out.println("Car stopped.");
}
}
java
interface A {
void showA();
interface B {
void showB();
class C implements A, B {
System.out.println("A");
obj.showA(); // Output: A
obj.showB(); // Output: B
java
interface Calculator {
1. Upcasting:
○ ChildClass obj = new ParentClass()
○ Automatic (implicit)
○ Lose access to child-specific methods
2. Downcasting:
○ ParentClass obj = new ChildClass()
○ Needs explicit casting (ChildClass)
○ Must check with instanceof first
○ Gives access to child-specific methods
package Demo;
public class Main {
public static void main(String[] args) {
Engine engine = new Bike(); // Upcasting
// engine.start();
// engine.kickStart();
// Downcasting - must check first
if (engine instanceof Bike) {
Bike bike = (Bike) engine; //Down casting
bike.kickStart(); // Now we can use BikeEngine methods
}
}
}
package Demo;
public class Bike extends Engine {
public void start() {
System.out.println("Put-put! Bike engine starts");
}
public void kickStart() {
System.out.println("Kick starting bike!");
}
}
package Demo;
public class Engine {
public void start() {
System.out.println("Engine start called...");
}
}
package Demo;
public class Car implements Engine {
// Non-abstract method: has a body
public void fuelType() {
System.out.println("Car uses diesel.");
}
// Implementing interface method
public void engineType() {
System.out.println("Car has a 4-stroke engine.");
}
}
package Demo;
public interface Engine {
int maxSpeed = 120;
// public static final int maxSpeed = 120;
void engineType();
// public abstract void engineType();
// String getEngineName(int engineId);
// public abstract String getEngineName(int engineId);
}
Difference between String and StringBuilder?
String s = "Hello";
s = s + " World";
s = s + "!";
System.out.println(s);
● " World" and "!" are also stored in String Pool. // 2 object
○ "Hello"
○ "Hello World"
○ "Hello World!"
→ 3 different String objects created in heap memory.
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
sb.append("!");
System.out.println(sb.toString());
● "Hello", " World", and "!" are String literals in the pool. // 3 objects
✅ Advantage:
● More memory-efficient and faster for repeated changes.
5 Java Access Modifiers
public ✅ ✅ ✅ ✅
protected ✅ ✅ ✅ ❌
default (no modifier) ✅ ✅ ❌ ❌
private ✅ ❌ ❌ ❌
Examples:
❌
BankAccount acc = new BankAccount();
❌
// System.out.println(acc.balance); Error (private)
✅
// acc.showBalance(); Error (private)
acc.display(); // Accessible via public method
}
}
Key Characteristics:
Key Characteristics:
// Append operations
sb.append(" is");
sb.append(" awesome!");
System.out.println(sb); // Output: Java is awesome!
sb.delete(5, 12);
System.out.println(sb); // Output: Java is awesome!
// Reverse
sb.reverse();
System.out.println(sb); // Output: !emosewa si avaJ
}
}
Key Characteristics:
✔ Mutable like StringBuilder
✔ Thread-safe (synchronized methods)
✔ Slightly slower than StringBuilder due to synchronization
// Append operations
sbf.append("-Safe");
System.out.println(sbf); // Output: Thread-Safe
// Thread-safe modification
Runnable task = () -> {
sbf.append("!");
};
new Thread(task).start();
new Thread(task).start();
// StringBuilder
start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ITERATIONS; i++) {
sb.append("a");
}
System.out.println("StringBuilder time: " + (System.currentTimeMillis() - start) +
"ms");
// StringBuffer
start = System.currentTimeMillis();
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < ITERATIONS; i++) {
sbf.append("a");
}
System.out.println("StringBuffer time: " + (System.currentTimeMillis() - start) +
"ms");
}
}
Typical Output:
text
String time: 4235ms
StringBuilder time: 5ms
StringBuffer time: 8ms
7. Java Arrays
An array is a container object that holds a fixed number of values of a single type.
Arrays are indexed, starting from 0.
7.1 1D Array
java
public class Main {
public static void main(String[] args) {
// Declaration & Initialization
int[] numbers = {10, 20, 30, 40, 50};
// Accessing elements
System.out.println("First Element: " + numbers[0]); // Output: 10
System.out.println("Third Element: " + numbers[2]); // Output: 30
// Modifying an element
numbers[1] = 25;
System.out.println("Modified Second Element: " + numbers[1]); // Output: 25
Example: 2D Array
java
public class Main {
public static void main(String[] args) {
// Declaration & Initialization
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Accessing elements
System.out.println("Element at [0][1]: " + matrix[0][1]); // Output: 2
System.out.println("Element at [2][2]: " + matrix[2][2]); // Output: 9
// Modifying an element
matrix[1][1] = 50;
System.out.println("Modified Element at [1][1]: " + matrix[1][1]); // Output: 50
7.3. 3D Arrays
A 3D array is an array of 2D arrays, useful for representing 3D structures like cubes.
Example: 3D Array
java
public class Main {
public static void main(String[] args) {
// Declaration & Initialization
int[][][] cube = {
{
{1, 2, 3},
{4, 5, 6}
},
{
{7, 8, 9},
{10, 11, 12}
}
};
// Accessing elements
System.out.println("Element at [0][1][2]: " + cube[0][1][2]); // Output: 6
System.out.println("Element at [1][0][1]: " + cube[1][0][1]); // Output: 8
// Modifying an element
cube[1][1][0] = 100;
System.out.println("Modified Element at [1][1][0]: " + cube[1][1][0]); // Output: 100
// Length of dimensions
System.out.println("Depth (Z-axis): " + cube.length); // Output: 2
System.out.println("Rows (Y-axis): " + cube[0].length); // Output: 2
System.out.println("Columns (X-axis): " + cube[0][0].length); // Output: 3
Key Takeaways
8. Java Exceptions
Output:
text
Exception in thread "main" java.lang.ArithmeticException: / by zero
text
Unhandled exception: java.io.FileNotFoundException
Output:
text
Exception in thread "main" java.lang.NullPointerException
3. Errors
Output:
text
Exception in thread "main" java.lang.StackOverflowError
Output:
text
Error: Division by zero!
2. Using try-catch-finally
● finally block executes always, whether an exception occurs or not.
● Used for cleanup (e.g., closing files, database connections).
Example: try-catch-finally
java
public class Main {
public static void main(String[] args) {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[5]); // Throws ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Error: Array index out of bounds!");
} finally {
System.out.println("This will always execute.");
}
}
}
Output:
text
Error: Array index out of bounds!
This will always execute.
text
Error: File not found!
Output:
text
Exception in thread "main" java.lang.ArithmeticException: Access denied - You must
be at least 18!
Example: try-with-resources
java
import java.io.*;
text
Error: example.txt (No such file or directory)
5. Summary Table
Output:
text
Thread is running…
9.2. Multithreading in Java
Multithreading allows concurrent execution of two or more threads for maximum CPU
utilization.
Output:
text
Thread (Runnable) is running...
9.3. Thread Lifecycle
A thread can be in one of these states:
State Description
Output:
text
Before start(): NEW
After start(): RUNNABLE
During sleep(): TIMED_WAITING
After completion: TERMINATED
9.4. Process vs. Thread
Feature Process Thread
t1.start();
t2.start();
t1.join();
t2.join();
Output:
text
Final Count: 2000
Example: ExecutorService
java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
executor.shutdown();
}
}
Output (Sample):
text
Thread: pool-1-thread-1
Thread: pool-1-thread-2
Thread: pool-1-thread-3
Thread: pool-1-thread-1
Thread: pool-1-thread-2
Example:
java
import java.util.*;
Implementations:
Example:
java
import java.util.*;
Memory Usage
● ArrayList: Generally uses less memory as it only stores elements
● LinkedList: Uses more memory due to storing both elements and node
references (next/previous pointers)
2. Key Differences
Feature ArrayList LinkedList
package Demo;
import java.util.LinkedList;
public class Demo extends Object {
public static void main(String[] args) {
LinkedList<String> fruits = new LinkedList<>();
// Adding elements (O(1) at end)
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
// Fast insertion at start (O(1))
fruits.addFirst("Mango");
// Fast removal at end (O(1))
fruits.removeLast();
// Slow random access (O(n))
System.out.println(fruits.get(1)); // Traverses nodes
// Slower iteration (due to pointer chasing)
for (String fruit : fruits) {
System.out.println(fruit);
}
}
}
10.2. Set Interface
A Set is a collection that does not allow duplicate elements.
Implementations:
Example:
java
import java.util.*;
1. Introduction
In Java, HashSet and TreeSet are two implementations of the Set interface
under java.util. Both store unique elements, but they differ in ordering,
performance, and underlying implementation.
import java.util.HashSet;
❌
// No null allowed (throws NullPointerException)
// cities.add(null); // Runtime error
}
}
Implementations:
Example:
java
import java.util.*;
Null Keys Allows one null key No null keys (if natural
ordering)
System.out.println(countryPopulations);
// Output varies: {USA=333000000, China=1412000000,
India=1418000000}
System.out.println(countryPopulations);
// Output: {China=1412000000, India=1417000000, USA=333000000} (alphabetical
order)
❌
// No null keys allowed (throws NullPointerException)
// countryPopulations.put(null, 0); // Runtime error
Implementations:
Example:
java
import java.util.*;
Example:
java
// Array Example
int[] arr = new int[3];
arr[0] = 10;
// ArrayList Example
ArrayList<Integer> list = new ArrayList<>();
list.add(10);
// Copy file
Files.copy(Paths.get("source.txt"), Paths.get("dest.txt"));
// Delete file
Files.deleteIfExists(Paths.get("file.txt"));
❌ Problem:
If you change how Engine works (e.g. rename method, add parameters), both
Bike and Car must be changed.
package Demo;
public class Main {
public static void main(String[] args) {
Bike bike = new Bike();
bike.startBike();
Car car = new Car();
car.startCar();
}
}
package Demo;
public class Bike {
Engine engine = new Engine(); // Tightly coupled
void startBike() {
engine.start();
System.out.println("Bike started");
}
}
package Demo;
public class Car {
Engine engine = new Engine(); // Tightly coupled
void startCar() {
engine.start();
System.out.println("Car started");
}
}
package Demo;
public class Engine {
void start() {
System.out.println("Engine started");
}
}
✅ Benefit:
● You can reuse the same Engine object.
● Bike and Car don’t depend on how Engine is created — this makes
testing and changes easier.
package Demo;
public class Main {
public static void main(String[] args) {
Bike bike = new Bike(new Engine());
bike.startBike();
Car car = new Car(new Engine());
car.startCar();
}
}
package Demo;
public class Car {
// Engine engine = new Engine(); // Tightly coupled
// void startCar() {
// engine.start();
// System.out.println("Car started");
// }
Engine engine;
// Constructor Injection
Car(Engine engine) {
this.engine = engine;
}
void startCar() {
engine.start();
System.out.println("Car started");
}
}
package Demo;
public class Bike {
// Engine engine = new Engine(); // Tightly coupled
//
// void startBike() {
// engine.start();
// System.out.println("Bike started");
// }
Engine engine;
// Constructor Injection
Bike(Engine engine) {
this.engine = engine;
}
void startBike() {
engine.start();
System.out.println("Bike started");
}
}
package Demo;
public class Engine {
void start() {
System.out.println("Engine started");
}
}
package Demo;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
// list.add(123); // Compile-time error
String text = list.get(0); // No need to cast
System.out.println(text);
}
}
package Demo;
public class Box<T> {
T value;
void set(T value) {
this.value = value;
}
T get() {
return value;
}
}
Lambda:
1.1
package Demo;
public class Test {
int add(int a,int b) {
return a+b;
}
}
package Demo;
public class Demo{
public static void main(String[] args) {
Demo d = new Demo();
d.display(new Test());
}
public void display(Test t) {
int sum = t.add(5, 10);
System.out.println(sum);
}
}
1.2
package Demo;
public interface Test {
int add(int a,int b);
}
package Demo;
public class Demo implements Test{
public static void main(String[] args) {
Demo d = new Demo();
int sum = d.add(5, 10);
System.out.println(sum);
}
@Override
public int add(int a, int b) {
// TODO Auto-generated method stub
return a+b;
}
// public void display(Test t) {
// int sum = t.add(5, 10);
// System.out.println(sum);
// }
}
1. ✅ Achieve Abstraction
🔁 Multiple Inheritance and
🔌 Loose Coupling
2.
3.
Anonymous Inner Class
✅ Definition:
An anonymous inner class is a one-time use class without a name that:
🔍 Why "anonymous"?
Because you are not giving the class a name — you're creating an object and
defining the class body at the same time.
package Demo;
public class Demo {
public static void main(String[] args) {
Demo d = new Demo();
// Test t = new Test() {
// @Override
// public int add(int a,int b) {
// return a+b;
// }
// };
d.display((a,b)->a+b);
}
public void display(Test t) {
int sum = t.add(5, 10);
System.out.println(sum);
}
}
package Demo;
@FunctionalInterface
public interface Test {
int add(int a,int b);
}
Lambda:
package Demo;
public class Demo {
public static void main(String[] args) {
Demo d =new Demo();
// d.display(new Test());
d.display((a,b)-> a+b);
}
public void display(Test t) {
int sum = t.add(5, 10);
System.out.println(sum);
}
}
(a, b) -> a + b
1 Lambda Syntax
java
(parameters) -> expression
(parameters) -> { statements; }
3 Practical Examples
java
import java.util.*;
import java.util.function.*;
// Function example
Function<String, Integer> lengthFinder = s -> s.length();
System.out.println(lengthFinder.apply("Java")); // 4
// Consumer example
Consumer<String> printer = s -> System.out.println(">> " + s);
printer.accept("Hello"); // >> Hello
// Runnable example
Runnable task = () -> System.out.println("Task executed");
new Thread(task).start();
}
}
4 Method References
java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Key Takeaways
1. File I/O: Prefer java.nio.Files for modern operations
2. Generics: Provide type safety and reduce casting
3. Lambdas: Enable functional programming with concise syntax
4. Best Practice: Always use try-with-resources for file operations
Syntax:
java
(parameters) -> { body }
Example:
java
// Traditional approach (Anonymous class)
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("Running without Lambda");
}
};
// Using Lambda
Runnable runnable2 = () -> System.out.println("Running with Lambda");
Example:
java
import java.util.function.*;
Example:
java
import java.util.*;
import java.util.stream.*;
Example:
java
import java.util.*;
// Using Lambda
names.forEach(name -> System.out.println(name));
Example:
java
interface Vehicle {
void start(); // Abstract method
Common Methods:
Method Description
Example:
java
import java.util.Optional;
// Functional style
System.out.println(name.orElse("Name not found"));
}
Key Classes:
Class Description
package Demo;
public interface Engine {
public abstract void start() ;
abstract void stop();
default void show() {
System.out.println("Default method in interface");
}
static int square(int x) {
return x * x;
}
default void display() {
System.out.println("Default method in interface");
}
static int add(int x,int y) {
return x + y;
}
}
package Demo;
public class Main {
public static void main(String[] args) {
Engine engine = new Engine() {
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void start() {
// TODO Auto-generated method stub
}
};
engine.show();
System.out.println(Engine.square(3));
}
}
4. 🌊
Stream API
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
5. 🎁 Optional Class
✅ What is Optional<T>?
Optional is a container object that may or may not contain a non-null value.
Optional<String> name = Optional.of("John");
7. 🔍 Method References
List<String> list = Arrays.asList("a", "b", "c");
list.forEach(System.out::println);
OR
list.forEach(s -> System.out.println(s));
OR
Consumer<String> printConsumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
// Pass it to forEach
list.forEach(printConsumer);
OR
List<String> list = Arrays.asList("a", "b", "c");
for (String s : list) {
System.out.println(s);
}
System.out.println();
🧠 Summary Table:
Part Type Description
Conclusion
Java 8 revolutionized Java with lambda expressions, streams, functional interfaces,
and modern APIs like Optional and java.time. These features improve code
readability, maintainability, and performance.
12. Java Memory Management & Memory
Leaks - Professional Documentation
java
private static final Map<Integer, WeakReference<String>> CACHE = new
HashMap<>();
java
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
// Automatically closes reader
}
✅ Solution 3: Evict Unused Objects
● Use WeakHashMap or LinkedHashMap with removeEldestEntry().
java
private static final Map<Integer, String> CACHE = new LinkedHashMap<>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
return size() > 100; // Keep only 100 entries
}
};
java
threadLocal.set(data);
try {
// Use data
} finally {
threadLocal.remove(); // Clean up
}
Conclusion
● Memory leaks occur due to unintentional object retention.
● Detection tools (VisualVM, MAT) help identify leaks.
● Solutions: Weak references, proper resource closing, eviction policies.