Complete Java Fundamentals for Beginners

A comprehensive 12+ hour Java course covering core concepts from setup through advanced topics like threads, collections, and streams. Learn JDK installation, variables, data types, operators, OOP principles, exception handling, multithreading, collection APIs, and functional programming with streams.

Why Java Matters

Java's Dominance in Enterprise

Java consistently ranks in the top 5 programming languages because it supports multiple use cases: enterprise applications, web development, mobile development, and more. Most large companies prefer Java as their primary language.

JVM Enables Language Flexibility

Java's JVM (Java Virtual Machine) allows multiple languages—Kotlin, Scala, Groovy—to run on the same platform. Learning Java makes it easier to transition to other JVM-based languages.

Java's Readability and Maintainability

While Java requires more boilerplate code than Python or JavaScript at first, it is highly readable and maintainable. Once you build larger applications, the line count remains similar, but the code clarity makes Java preferred for long-term projects.

Java History and Versions

Java's Origin and Evolution

Java was created in 1995 by Sun Microsystems under James Gosling's leadership. Oracle later acquired Sun and now maintains Java. The language updates every six months with new features, though not all are major updates.

LTS Versions for Stability

Not every Java version receives long-term support (LTS). Java 17 is an LTS version, making it ideal for production use. Choosing LTS versions ensures stability and extended support.

Setting Up Java Development

JDK vs JRE vs JVM

JDK (Java Development Kit) is for developers and includes the compiler and runtime. JRE (Java Runtime Environment) is for end-users and includes JVM and libraries. JVM (Java Virtual Machine) executes the bytecode. Developers install JDK; users only need JRE.

Installation and Path Configuration

Download JDK 17 (LTS) and set the system PATH variable to the JDK bin folder. Verify installation by running 'java -version' and 'javac -version' in the command prompt.

IDE Choice: VS Code

VS Code is lightweight and suitable for beginners. Other options include Eclipse, IntelliJ IDEA (paid Ultimate version), and NetBeans. VS Code allows you to write, compile, and run Java code with optional extensions.

Java Compilation and Execution

Two-Step Process: Compile and Run

Java requires two steps: (1) Compile .java file to .class bytecode using 'javac filename.java', (2) Run bytecode on JVM using 'java classname'. The .class file is platform-independent bytecode that JVM interprets.

Platform Independence Through JVM

Java is write-once-run-anywhere because the bytecode runs on any JVM. The JVM itself is platform-dependent (Windows, Mac, Linux), but your compiled code works everywhere JVM is installed.

Main Method Requirement

Every Java application needs a main method with the exact signature: 'public static void main(String[] args)'. JVM looks for this method as the entry point to start execution.

Hello World and Basic Syntax

Class and File Structure

Java requires code to be inside a class. The class name should match the filename (e.g., Hello.java contains class Hello). Every Java file must have .java extension.

Printing Output

Use 'System.out.println()' to print text and move to a new line, or 'System.out.print()' to print without a newline. Always end statements with a semicolon.

JShell for Quick Testing

Java 9+ includes JShell, an interactive shell for testing code snippets without compilation. Type 'jshell' in terminal to experiment with Java syntax quickly.

Variables and Data Types

Variable Declaration and Assignment

Variables store data in boxes with a name, type, and value. Syntax: 'type variableName = value;'. Java is strongly typed—you must declare the type before use. The equals sign assigns the right-side value to the left-side variable.

Primitive Data Types Overview

Java has 8 primitive types: byte, short, int, long (integers); float, double (decimals); char (single character); boolean (true/false). Each has a specific size and range.

Integer Type Ranges

Byte ranges from -128 to 127 (1 byte). Short ranges from -32,768 to 32,767 (2 bytes). Int ranges from about -2.1 billion to 2.1 billion (4 bytes). Long supports larger values (8 bytes, append L to literal).

Float vs Double

Float uses 4 bytes with limited precision; double uses 8 bytes with higher precision. By default, decimal literals are treated as double. Append F to specify float (e.g., 5.6F).

Character and Boolean Types

Char stores a single character in single quotes (e.g., 'a') and uses 2 bytes (Unicode). Boolean stores only true or false—not 1 or 0. Both are primitive types.

Number Literals and Formats

Decimal numbers are base 10. Binary literals use 0b prefix (e.g., 0b101 = 5). Hexadecimal literals use 0x prefix (e.g., 0x7E = 126). Underscores in numbers improve readability (e.g., 1_000_000).

Type Conversion and Casting

Implicit Conversion (Widening)

When assigning a smaller type to a larger type, Java automatically converts. Example: byte to int. No data loss occurs because the larger type can hold all values of the smaller type.

Explicit Casting (Narrowing)

To assign a larger type to a smaller type, use explicit casting: '(byte) intValue'. This may lose data. Example: 257 cast to byte becomes 1 (using modulo with range 256).

Type Promotion in Operations

When performing operations on different types, Java promotes smaller types to larger ones. Example: byte * byte results in int. This prevents overflow and data loss.

Operators and Expressions

Arithmetic Operators

Addition (+), subtraction (-), multiplication (*), division (/), and modulus (%) perform basic math. Division of integers returns an integer (truncates decimals). Modulus returns the remainder.

Assignment Operators

Basic assignment (=) assigns right value to left variable. Compound operators (+=, -=, *=, /=) combine operation and assignment. Example: 'num += 2' is equivalent to 'num = num + 2'.

Increment and Decrement

++ increments by 1, -- decrements by 1. Pre-increment (++num) increments before use; post-increment (num++) increments after use. Both modify the variable.

Relational Operators

Compare values: == (equal), != (not equal), > (greater), < (less), >= (greater or equal), <= (less or equal). All return boolean (true/false).

Logical Operators

AND (&&) returns true if both conditions are true. OR (||) returns true if at least one condition is true. NOT (!) inverts the boolean value.

Ternary Operator

Shorthand for if-else: 'condition ? valueIfTrue : valueIfFalse'. Returns one of two values based on a condition.

Control Flow Statements

If-Else Conditionals

Execute code based on conditions. If condition is true, execute if block; otherwise, execute else block. Use else-if for multiple conditions.

Switch Statements

Select one of many code blocks to execute based on a value. Each case must end with break to prevent fall-through. Default case executes if no case matches.

For Loops

Repeat code a fixed number of times. Syntax: 'for(init; condition; increment)'. Initialize counter, check condition, execute body, then increment.

While and Do-While Loops

While loops repeat while condition is true. Do-while loops execute body first, then check condition (always runs at least once).

Enhanced For Loop

Simplified loop for arrays and collections: 'for(type variable : collection)'. Automatically iterates through each element without managing index.

Break and Continue

Break exits the loop immediately. Continue skips the current iteration and moves to the next. Both are useful for controlling loop flow.

Arrays

Array Declaration and Initialization

Arrays store multiple values of the same type in fixed size. Declare with 'type[] arrayName = new type[size]'. Access elements with index starting from 0.

Array Operations

Access elements using index notation (array[0]). Modify elements with assignment. Iterate using for loops or enhanced for loops. Arrays have fixed size—cannot expand.

Multi-dimensional Arrays

Arrays of arrays create matrices. Declare with 'type[][] arrayName'. Access with two indices: array[row][column].

Object-Oriented Programming Basics

Classes and Objects

A class is a blueprint; an object is an instance of a class. Classes define properties (variables) and methods (functions). Create objects with 'new ClassName()'.

Constructors

Constructors initialize objects when created. They have the same name as the class and no return type. Can have parameters to set initial values.

Methods

Methods are functions inside classes. Define with 'returnType methodName(parameters)'. Call with 'object.methodName(arguments)'.

Encapsulation with Access Modifiers

Public members are accessible everywhere. Private members are only accessible within the class. Protected members are accessible within package and subclasses. Use getters and setters to control access.

Inheritance

A class can inherit from another class using 'extends'. Child class inherits properties and methods from parent class. Use 'super' to call parent class methods.

Polymorphism

Objects can take multiple forms. Method overriding allows child classes to redefine parent methods. Method overloading allows multiple methods with the same name but different parameters.

Abstraction

Abstract classes and interfaces define contracts without implementation. Abstract methods must be implemented by subclasses. Interfaces define what a class should do, not how.

Exception Handling

Try-Catch Blocks

Wrap risky code in try block. If exception occurs, catch block handles it. Syntax: 'try { risky code } catch (ExceptionType e) { handle error }'.

Finally Block

Finally block executes regardless of whether exception occurred. Use for cleanup code (closing files, releasing resources). Executes after try or catch block.

Throw and Throws

Throw keyword manually throws an exception. Throws keyword in method signature declares that method may throw exceptions. Caller must handle them.

Common Exception Types

NullPointerException occurs when accessing null object. ArrayIndexOutOfBoundsException occurs with invalid array index. ArithmeticException occurs with division by zero. IOException occurs with file operations.

Multithreading

Thread Creation

Create threads by extending Thread class or implementing Runnable interface. Override run() method with code to execute. Call start() to begin execution, not run().

Thread States

New state: thread created. Runnable state: ready to run. Running state: executing on CPU. Waiting state: paused (sleep, wait). Dead state: execution complete.

Sleep and Join Methods

sleep() pauses thread for milliseconds. join() makes main thread wait for other threads to complete. Both throw InterruptedException.

Synchronization for Shared Resources

When multiple threads access shared variables, use synchronized keyword to ensure only one thread accesses at a time. Prevents data corruption and race conditions.

Race Conditions Example

When two threads increment same variable simultaneously, both may read old value before either writes new value. Result: lost increment. Synchronization prevents this.

Collections Framework

Collection API Overview

Collection API provides interfaces and classes for storing groups of objects. Includes List (ordered, allows duplicates), Set (unique values), Queue (FIFO), and Map (key-value pairs).

ArrayList Implementation

ArrayList is a dynamic array that grows automatically. Use 'List<Integer> list = new ArrayList<>()'. Add elements with add(), access with get(index), remove with remove().

Generics for Type Safety

Use angle brackets to specify element type: 'List<Integer> list'. Prevents ClassCastException at runtime. Compiler catches type mismatches at compile time.

HashSet for Unique Values

HashSet stores unique values only. Duplicates are ignored. Order is not guaranteed. Use when you need fast lookup and uniqueness.

TreeSet for Sorted Values

TreeSet stores unique values in sorted order. Slower than HashSet but maintains order. Use when you need sorted unique values.

HashMap for Key-Value Storage

HashMap stores key-value pairs. Keys must be unique. Use put(key, value) to add, get(key) to retrieve. Order not guaranteed.

Iterator for Collection Traversal

Iterator provides hasNext() and next() methods to traverse collections. Use in while loop: 'while(iterator.hasNext()) { element = iterator.next(); }'.

Sorting and Comparators

Collections.sort() Method

Sort collections using Collections.sort(list). Sorts in natural order (ascending for numbers). Works with any comparable type.

Comparator for Custom Sorting

Implement Comparator interface to define custom sort logic. compare() method returns negative (less), zero (equal), or positive (greater). Pass to sort() method.

Comparable Interface

Implement Comparable in class to define natural sort order. compareTo() method compares this object with another. Returns negative, zero, or positive.

Lambda Expressions for Comparators

Use lambda syntax for concise comparators: '(a, b) -> a.getAge() - b.getAge()'. Functional interface allows single-line implementation.

Stream API

Stream Basics

Stream is a sequence of elements supporting functional operations. Create with collection.stream(). Streams are one-time use—cannot reuse after terminal operation.

Filter Operation

Filter removes elements not matching condition. Syntax: 'stream.filter(predicate)'. Predicate returns boolean. Returns new stream with matching elements.

Map Operation

Map transforms each element. Syntax: 'stream.map(function)'. Function takes element, returns transformed value. Returns new stream with transformed elements.

Reduce Operation

Reduce combines all elements into single value. Syntax: 'stream.reduce(initialValue, (accumulator, element) -> accumulator + element)'. Returns final result.

ForEach Terminal Operation

ForEach executes action for each element. Syntax: 'stream.forEach(action)'. Terminal operation—ends stream pipeline. No return value.

Sorted Operation

Sort stream elements. Syntax: 'stream.sorted()' for natural order or 'stream.sorted(comparator)' for custom order. Returns new sorted stream.

Chaining Stream Operations

Combine multiple operations: 'stream.filter(...).map(...).sorted(...).forEach(...)'. Each intermediate operation returns new stream. Terminal operation ends chain.

Functional Interfaces

Predicate: tests condition, returns boolean. Function: transforms value. Consumer: accepts value, no return. BinaryOperator: combines two values. All support lambda expressions.

Notable quotes

Java is difficult just to start with, but once you make a big application the number of lines will remain almost same. — Naveen Reddy
Java is one of the most readable languages. If you are looking at someone else's code you can read the Java code line by line. — Naveen Reddy
It's not difficult, it's just unfamiliar. — Venkat Subramaniam (referenced by Naveen)

Action items

  • Download and install JDK 17 (LTS version) from Oracle website
  • Set system PATH variable to JDK bin folder and verify with 'java -version' and 'javac -version'
  • Install VS Code and configure it for Java development
  • Write and compile your first Hello World program
  • Practice creating variables with different primitive data types
  • Experiment with type casting and conversion
  • Create classes with constructors and methods
  • Practice control flow statements (if-else, loops, switch)
  • Create and manipulate arrays
  • Implement exception handling with try-catch-finally blocks
  • Create and run multiple threads with synchronization
  • Work with Collections: ArrayList, HashSet, HashMap
  • Implement custom sorting with Comparator and Comparable
  • Use Stream API for functional operations on collections
  • Build a small project combining multiple concepts learned
Telusko
12 hr 23 min video
3 min read
Complete Java Fundamentals for Beginners
You just saved 12 hr 20 min.
The big takeaway
A comprehensive 12+ hour Java course covering core concepts from setup through advanced topics like threads, collections, and streams. Learn JDK installation, variables, data types, operators, OOP principles, exception handling, multithreading, collection APIs, and functional programming with streams.
Why Java Matters
Java's Dominance in Enterprise
Java consistently ranks in the top 5 programming languages because it supports multiple use cases: enterprise applications, web development, mobile development, and more. Most large companies prefer Java as their primary language.
JVM Enables Language Flexibility
Java's JVM (Java Virtual Machine) allows multiple languages—Kotlin, Scala, Groovy—to run on the same platform. Learning Java makes it easier to transition to other JVM-based languages.
Java's Readability and Maintainability
While Java requires more boilerplate code than Python or JavaScript at first, it is highly readable and maintainable. Once you build larger applications, the line count remains similar, but the code clarity makes Java preferred for long-term projects.
Java History and Versions
Java's Origin and Evolution
Java was created in 1995 by Sun Microsystems under James Gosling's leadership. Oracle later acquired Sun and now maintains Java. The language updates every six months with new features, though not all are major updates.
1995
Java created by Sun Microsystems
Later
Oracle acquires Sun
Every 6 months
New Java versions released
Java development timeline
LTS Versions for Stability
Not every Java version receives long-term support (LTS). Java 17 is an LTS version, making it ideal for production use. Choosing LTS versions ensures stability and extended support.
Setting Up Java Development
JDK vs JRE vs JVM
JDK (Java Development Kit) is for developers and includes the compiler and runtime. JRE (Java Runtime Environment) is for end-users and includes JVM and libraries. JVM (Java Virtual Machine) executes the bytecode. Developers install JDK; users only need JRE.
1
JDK
For developers (includes compiler, JRE, JVM)
2
JRE
For end-users (includes JVM and libraries)
3
JVM
Executes bytecode (platform-dependent)
Java development stack hierarchy
Installation and Path Configuration
Download JDK 17 (LTS) and set the system PATH variable to the JDK bin folder. Verify installation by running 'java -version' and 'javac -version' in the command prompt.
1
Download JDK 17 from Oracle website
2
Run installer and complete setup
3
Set system PATH to JDK bin folder
4
Verify with 'java -version' and 'javac -version'
JDK installation steps
IDE Choice: VS Code
VS Code is lightweight and suitable for beginners. Other options include Eclipse, IntelliJ IDEA (paid Ultimate version), and NetBeans. VS Code allows you to write, compile, and run Java code with optional extensions.
Java Compilation and Execution
Two-Step Process: Compile and Run
Java requires two steps: (1) Compile .java file to .class bytecode using 'javac filename.java', (2) Run bytecode on JVM using 'java classname'. The .class file is platform-independent bytecode that JVM interprets.
1
Write code in .java file
2
Compile with javac to create .class bytecode
3
Run .class file on JVM with java command
4
JVM executes bytecode on your OS
Java compilation and execution flow
Platform Independence Through JVM
Java is write-once-run-anywhere because the bytecode runs on any JVM. The JVM itself is platform-dependent (Windows, Mac, Linux), but your compiled code works everywhere JVM is installed.
Main Method Requirement
Every Java application needs a main method with the exact signature: 'public static void main(String[] args)'. JVM looks for this method as the entry point to start execution.
Hello World and Basic Syntax
Class and File Structure
Java requires code to be inside a class. The class name should match the filename (e.g., Hello.java contains class Hello). Every Java file must have .java extension.
Printing Output
Use 'System.out.println()' to print text and move to a new line, or 'System.out.print()' to print without a newline. Always end statements with a semicolon.
JShell for Quick Testing
Java 9+ includes JShell, an interactive shell for testing code snippets without compilation. Type 'jshell' in terminal to experiment with Java syntax quickly.
Variables and Data Types
Variable Declaration and Assignment
Variables store data in boxes with a name, type, and value. Syntax: 'type variableName = value;'. Java is strongly typed—you must declare the type before use. The equals sign assigns the right-side value to the left-side variable.
Primitive Data Types Overview
Java has 8 primitive types: byte, short, int, long (integers); float, double (decimals); char (single character); boolean (true/false). Each has a specific size and range.
Integer Type Ranges
Byte ranges from -128 to 127 (1 byte). Short ranges from -32,768 to 32,767 (2 bytes). Int ranges from about -2.1 billion to 2.1 billion (4 bytes). Long supports larger values (8 bytes, append L to literal).
byte
1 byte
short
2 bytes
int
4 bytes
long
8 bytes
Integer type memory sizes
Float vs Double
Float uses 4 bytes with limited precision; double uses 8 bytes with higher precision. By default, decimal literals are treated as double. Append F to specify float (e.g., 5.6F).
float
4 bytes
double
8 bytes
Floating-point type memory comparison
Character and Boolean Types
Char stores a single character in single quotes (e.g., 'a') and uses 2 bytes (Unicode). Boolean stores only true or false—not 1 or 0. Both are primitive types.
Number Literals and Formats
Decimal numbers are base 10. Binary literals use 0b prefix (e.g., 0b101 = 5). Hexadecimal literals use 0x prefix (e.g., 0x7E = 126). Underscores in numbers improve readability (e.g., 1_000_000).
1
Decimal
Base 10 (normal numbers)
2
Binary
0b prefix (e.g., 0b101)
3
Hexadecimal
0x prefix (e.g., 0x7E)
4
Underscores
For readability (e.g., 1_000_000)
Number literal formats in Java
Type Conversion and Casting
Implicit Conversion (Widening)
When assigning a smaller type to a larger type, Java automatically converts. Example: byte to int. No data loss occurs because the larger type can hold all values of the smaller type.
Explicit Casting (Narrowing)
To assign a larger type to a smaller type, use explicit casting: '(byte) intValue'. This may lose data. Example: 257 cast to byte becomes 1 (using modulo with range 256).
Integer value
257
Cast to byte
1 (257 % 256)
Narrowing conversion example
Type Promotion in Operations
When performing operations on different types, Java promotes smaller types to larger ones. Example: byte * byte results in int. This prevents overflow and data loss.
Operators and Expressions
Arithmetic Operators
Addition (+), subtraction (-), multiplication (*), division (/), and modulus (%) perform basic math. Division of integers returns an integer (truncates decimals). Modulus returns the remainder.
1
+
Addition
2
-
Subtraction
3
*
Multiplication
4
/
Division (integer result)
5
%
Modulus (remainder)
Arithmetic operators
Assignment Operators
Basic assignment (=) assigns right value to left variable. Compound operators (+=, -=, *=, /=) combine operation and assignment. Example: 'num += 2' is equivalent to 'num = num + 2'.
1
=
Assign value
2
+=
Add and assign
3
-=
Subtract and assign
4
*=
Multiply and assign
5
/=
Divide and assign
Assignment operators
Increment and Decrement
++ increments by 1, -- decrements by 1. Pre-increment (++num) increments before use; post-increment (num++) increments after use. Both modify the variable.
Relational Operators
Compare values: == (equal), != (not equal), > (greater), < (less), >= (greater or equal), <= (less or equal). All return boolean (true/false).
1
==
Equal to
2
!=
Not equal to
3
>
Greater than
4
<
Less than
5
>=
Greater or equal
6
<=
Less or equal
Relational operators
Logical Operators
AND (&&) returns true if both conditions are true. OR (||) returns true if at least one condition is true. NOT (!) inverts the boolean value.
1
&&
AND (both true)
2
||
OR (at least one true)
3
!
NOT (inverts boolean)
Logical operators
Ternary Operator
Shorthand for if-else: 'condition ? valueIfTrue : valueIfFalse'. Returns one of two values based on a condition.
Control Flow Statements
If-Else Conditionals
Execute code based on conditions. If condition is true, execute if block; otherwise, execute else block. Use else-if for multiple conditions.
1
Evaluate condition
2
If true, execute if block
3
If false, execute else block
4
Continue execution
If-else flow
Switch Statements
Select one of many code blocks to execute based on a value. Each case must end with break to prevent fall-through. Default case executes if no case matches.
For Loops
Repeat code a fixed number of times. Syntax: 'for(init; condition; increment)'. Initialize counter, check condition, execute body, then increment.
1
Initialize counter
2
Check condition
3
Execute loop body
4
Increment counter
5
Repeat until condition false
For loop execution
While and Do-While Loops
While loops repeat while condition is true. Do-while loops execute body first, then check condition (always runs at least once).
Enhanced For Loop
Simplified loop for arrays and collections: 'for(type variable : collection)'. Automatically iterates through each element without managing index.
Break and Continue
Break exits the loop immediately. Continue skips the current iteration and moves to the next. Both are useful for controlling loop flow.
Arrays
Array Declaration and Initialization
Arrays store multiple values of the same type in fixed size. Declare with 'type[] arrayName = new type[size]'. Access elements with index starting from 0.
Array Operations
Access elements using index notation (array[0]). Modify elements with assignment. Iterate using for loops or enhanced for loops. Arrays have fixed size—cannot expand.
Multi-dimensional Arrays
Arrays of arrays create matrices. Declare with 'type[][] arrayName'. Access with two indices: array[row][column].
Object-Oriented Programming Basics
Classes and Objects
A class is a blueprint; an object is an instance of a class. Classes define properties (variables) and methods (functions). Create objects with 'new ClassName()'.
Constructors
Constructors initialize objects when created. They have the same name as the class and no return type. Can have parameters to set initial values.
Methods
Methods are functions inside classes. Define with 'returnType methodName(parameters)'. Call with 'object.methodName(arguments)'.
Encapsulation with Access Modifiers
Public members are accessible everywhere. Private members are only accessible within the class. Protected members are accessible within package and subclasses. Use getters and setters to control access.
1
public
Accessible everywhere
2
private
Accessible only in class
3
protected
Accessible in package and subclasses
4
default
Accessible in package only
Access modifiers in Java
Inheritance
A class can inherit from another class using 'extends'. Child class inherits properties and methods from parent class. Use 'super' to call parent class methods.
Polymorphism
Objects can take multiple forms. Method overriding allows child classes to redefine parent methods. Method overloading allows multiple methods with the same name but different parameters.
Abstraction
Abstract classes and interfaces define contracts without implementation. Abstract methods must be implemented by subclasses. Interfaces define what a class should do, not how.
Exception Handling
Try-Catch Blocks
Wrap risky code in try block. If exception occurs, catch block handles it. Syntax: 'try { risky code } catch (ExceptionType e) { handle error }'.
1
Execute code in try block
2
If exception occurs, jump to catch
3
Handle exception in catch block
4
Continue execution
Try-catch execution flow
Finally Block
Finally block executes regardless of whether exception occurred. Use for cleanup code (closing files, releasing resources). Executes after try or catch block.
Throw and Throws
Throw keyword manually throws an exception. Throws keyword in method signature declares that method may throw exceptions. Caller must handle them.
Common Exception Types
NullPointerException occurs when accessing null object. ArrayIndexOutOfBoundsException occurs with invalid array index. ArithmeticException occurs with division by zero. IOException occurs with file operations.
Multithreading
Thread Creation
Create threads by extending Thread class or implementing Runnable interface. Override run() method with code to execute. Call start() to begin execution, not run().
1
Create class extending Thread or implementing Runnable
2
Override run() method
3
Create thread object
4
Call start() to begin execution
Thread creation steps
Thread States
New state: thread created. Runnable state: ready to run. Running state: executing on CPU. Waiting state: paused (sleep, wait). Dead state: execution complete.
1
New
Thread created, not started
2
Runnable
Ready to run, waiting for CPU
3
Running
Executing on CPU
4
Waiting
Paused (sleep, wait)
5
Dead
Execution complete
Thread lifecycle states
Sleep and Join Methods
sleep() pauses thread for milliseconds. join() makes main thread wait for other threads to complete. Both throw InterruptedException.
Synchronization for Shared Resources
When multiple threads access shared variables, use synchronized keyword to ensure only one thread accesses at a time. Prevents data corruption and race conditions.
Without synchronization
Race condition, unpredictable results
With synchronization
Consistent, predictable results
Synchronization impact on shared resources
Race Conditions Example
When two threads increment same variable simultaneously, both may read old value before either writes new value. Result: lost increment. Synchronization prevents this.
2000 expected
Actual result without sync: ~1746
Race condition data loss example
Collections Framework
Collection API Overview
Collection API provides interfaces and classes for storing groups of objects. Includes List (ordered, allows duplicates), Set (unique values), Queue (FIFO), and Map (key-value pairs).
1
List
Ordered, allows duplicates, index-based
2
Set
Unique values, no duplicates, unordered
3
Queue
FIFO (first in, first out)
4
Map
Key-value pairs, unique keys
Collection types and characteristics
ArrayList Implementation
ArrayList is a dynamic array that grows automatically. Use 'List<Integer> list = new ArrayList<>()'. Add elements with add(), access with get(index), remove with remove().
Generics for Type Safety
Use angle brackets to specify element type: 'List<Integer> list'. Prevents ClassCastException at runtime. Compiler catches type mismatches at compile time.
HashSet for Unique Values
HashSet stores unique values only. Duplicates are ignored. Order is not guaranteed. Use when you need fast lookup and uniqueness.
TreeSet for Sorted Values
TreeSet stores unique values in sorted order. Slower than HashSet but maintains order. Use when you need sorted unique values.
HashMap for Key-Value Storage
HashMap stores key-value pairs. Keys must be unique. Use put(key, value) to add, get(key) to retrieve. Order not guaranteed.
Iterator for Collection Traversal
Iterator provides hasNext() and next() methods to traverse collections. Use in while loop: 'while(iterator.hasNext()) { element = iterator.next(); }'.
Sorting and Comparators
Collections.sort() Method
Sort collections using Collections.sort(list). Sorts in natural order (ascending for numbers). Works with any comparable type.
Comparator for Custom Sorting
Implement Comparator interface to define custom sort logic. compare() method returns negative (less), zero (equal), or positive (greater). Pass to sort() method.
Comparable Interface
Implement Comparable in class to define natural sort order. compareTo() method compares this object with another. Returns negative, zero, or positive.
Lambda Expressions for Comparators
Use lambda syntax for concise comparators: '(a, b) -> a.getAge() - b.getAge()'. Functional interface allows single-line implementation.
Stream API
Stream Basics
Stream is a sequence of elements supporting functional operations. Create with collection.stream(). Streams are one-time use—cannot reuse after terminal operation.
Filter Operation
Filter removes elements not matching condition. Syntax: 'stream.filter(predicate)'. Predicate returns boolean. Returns new stream with matching elements.
1
Define predicate condition
2
Apply filter to stream
3
Returns new stream with matching elements
4
Continue with other operations
Filter operation flow
Map Operation
Map transforms each element. Syntax: 'stream.map(function)'. Function takes element, returns transformed value. Returns new stream with transformed elements.
Reduce Operation
Reduce combines all elements into single value. Syntax: 'stream.reduce(initialValue, (accumulator, element) -> accumulator + element)'. Returns final result.
ForEach Terminal Operation
ForEach executes action for each element. Syntax: 'stream.forEach(action)'. Terminal operation—ends stream pipeline. No return value.
Sorted Operation
Sort stream elements. Syntax: 'stream.sorted()' for natural order or 'stream.sorted(comparator)' for custom order. Returns new sorted stream.
Chaining Stream Operations
Combine multiple operations: 'stream.filter(...).map(...).sorted(...).forEach(...)'. Each intermediate operation returns new stream. Terminal operation ends chain.
1
Create stream from collection
2
Apply filter (intermediate)
3
Apply map (intermediate)
4
Apply sorted (intermediate)
5
Apply forEach (terminal)
Stream operation chaining
Functional Interfaces
Predicate: tests condition, returns boolean. Function: transforms value. Consumer: accepts value, no return. BinaryOperator: combines two values. All support lambda expressions.
1
Predicate
Tests condition, returns boolean
2
Function
Transforms value
3
Consumer
Accepts value, no return
4
BinaryOperator
Combines two values
Functional interfaces in Stream API
Worth quoting
"Java is difficult just to start with, but once you make a big application the number of lines will remain almost same."
— Naveen Reddy, at [3:03]
"Java is one of the most readable languages. If you are looking at someone else's code you can read the Java code line by line."
— Naveen Reddy, at [3:33]
"It's not difficult, it's just unfamiliar."
— Venkat Subramaniam (referenced by Naveen), at [733:54]
Try this
Download and install JDK 17 (LTS version) from Oracle website
Set system PATH variable to JDK bin folder and verify with 'java -version' and 'javac -version'
Install VS Code and configure it for Java development
Write and compile your first Hello World program
Practice creating variables with different primitive data types
Experiment with type casting and conversion
Create classes with constructors and methods
Practice control flow statements (if-else, loops, switch)
Create and manipulate arrays
Implement exception handling with try-catch-finally blocks
Create and run multiple threads with synchronization
Work with Collections: ArrayList, HashSet, HashMap
Implement custom sorting with Comparator and Comparable
Use Stream API for functional operations on collections
Build a small project combining multiple concepts learned
Made with Glimpse by Wozart
glimpse.wozart.com/v/6zxq8zb0
Share this infographic

More like this