Generics, Collections, and Core Data Structures
Queues and FIFO Processing
You are viewing a free preview lesson.
Lesson Overview
Collections-এর মধ্যে List, Set, এবং Map আমরা already শিখেছি।
কিন্তু কিছু problem আছে যেখানে data শুধু store করলেই হয় না—processing order-ও গুরুত্বপূর্ণ।
Example:
First request আসে
↓
সেটি আগে process হবে
Second request আসে
↓
সেটি পরে process হবে
এই ordering model-কে বলা হয়:
FIFO
meaning:
First In, First Out
Java-তে FIFO-style processing-এর জন্য important abstraction হলো:
Queue<E>
এই lesson-এ আমরা শিখব:
- What a queue is
- FIFO ordering
Queue<E>ArrayDequeoffer()poll()peek()add()remove()element()- Queue traversal
- Queue size and emptiness
- Queue as an interface
- Why
ArrayDequeis usually a strong default - Queue vs
List - Real backend-style queue use cases
- Common mistakes
- Designing queue-processing methods
What Is a Queue?
Imagine a line of people waiting at a counter।
The first person who joins the line should normally be served first।
Conceptually:
Front
↓
Sakib → Subu → Sumu → Nur
↑
Back
If Sakib entered first, Sakib leaves first।
This behavior is:
FIFO
or:
First In, First Out
Queue Operations
A queue normally needs three fundamental operations:
Add an item to the back
Remove the item from the front
Inspect the item at the front
Conceptually:
offer → add to back
poll → remove from front
peek → inspect front
Java Queue<E>
Java provides:
java.util.Queue
Queue is an interface।
Example:
Queue<String> tasks;
This means:
A queue containing String values
But because Queue is an interface, we need an implementation।
A common implementation is:
ArrayDeque
Creating a Queue
import java.util.ArrayDeque;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<String> tasks =
new ArrayDeque<>();
}
}
Notice the declaration:
Queue<String> tasks
and implementation:
new ArrayDeque<>()
This follows an important design principle:
Program to an abstraction
when the abstraction expresses what you need.
The variable promises queue behavior।
The implementation provides it।
Adding Elements with offer()
Example:
Queue<String> tasks =
new ArrayDeque<>();
tasks.offer(
"Send email"
);
tasks.offer(
"Generate invoice"
);
tasks.offer(
"Update report"
);
Conceptually:
Front
↓
Send email
Generate invoice
Update report
↑
Back
Why offer()?
For queue-style code, offer() communicates intent clearly:
Add this item to the queue.
Example:
tasks.offer(
"Process enrollment"
);
Removing with poll()
poll() removes and returns the front element।
Example:
String task =
tasks.poll();
If queue contains:
Send email
Generate invoice
Update report
then:
task = "Send email"
and queue becomes:
Generate invoice
Update report
FIFO in Action
Queue<String> tasks =
new ArrayDeque<>();
tasks.offer(
"First"
);
tasks.offer(
"Second"
);
tasks.offer(
"Third"
);
System.out.println(
tasks.poll()
);
System.out.println(
tasks.poll()
);
System.out.println(
tasks.poll()
);
Output:
First
Second
Third
That is FIFO।
Inspecting with peek()
Sometimes we want to see the front element without removing it।
Use:
peek()
Example:
Queue<String> tasks =
new ArrayDeque<>();
tasks.offer(
"Send email"
);
tasks.offer(
"Generate invoice"
);
String next =
tasks.peek();
Now:
next = "Send email"
but the queue still contains both elements।
peek() vs poll()
peek()
→ inspect front
→ does not remove
poll()
→ returns front
→ removes it
Complete Example
import java.util.ArrayDeque;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<String> tasks =
new ArrayDeque<>();
tasks.offer(
"Send verification email"
);
tasks.offer(
"Generate certificate"
);
tasks.offer(
"Update learner progress"
);
System.out.println(
"Next: "
+ tasks.peek()
);
while (
!tasks.isEmpty()
) {
String task =
tasks.poll();
System.out.println(
"Processing: "
+ task
);
}
}
}
Output:
Next: Send verification email
Processing: Send verification email
Processing: Generate certificate
Processing: Update learner progress
What Happens on an Empty Queue?
Suppose:
Queue<String> tasks =
new ArrayDeque<>();
Then:
tasks.poll()
returns:
null
and:
tasks.peek()
also returns:
null
This makes them convenient when absence is expected and handled।
Example
String task =
tasks.poll();
if (
task == null
) {
System.out.println(
"No task available."
);
}
Queue Has Two Method Families
Java Queue provides two styles of operations।
One style returns a special value when an operation cannot be completed normally।
Examples:
offer()
poll()
peek()
Another style throws an exception in corresponding situations।
Examples:
add()
remove()
element()
Queue Method Pairs
The important pairs are:
Add:
add()
offer()
Remove:
remove()
poll()
Inspect:
element()
peek()
poll() vs remove()
On a non-empty queue, both remove the front element।
Example:
queue.poll();
and:
queue.remove();
But on an empty queue:
queue.poll()
returns:
null
while:
queue.remove()
throws:
NoSuchElementException
peek() vs element()
On a non-empty queue, both inspect the front।
But on an empty queue:
queue.peek()
returns:
null
while:
queue.element()
throws:
NoSuchElementException
offer() vs add()
For many general-purpose queue implementations, both successfully add elements।
But conceptually:
offer()
is designed for queue insertion where capacity restrictions may exist।
If an insertion cannot happen:
offer()
can report failure via its return value।
boolean added =
queue.offer(
value
);
add() follows the general Collection contract and may throw an exception when insertion cannot be performed because of restrictions।
For ordinary queue-oriented code, offer() is often the clearest choice।
Recommended Queue Vocabulary
For queue-style processing, prefer learning this trio first:
offer()
poll()
peek()
Why?
Because they directly communicate queue behavior and handle empty-state inspection/removal without requiring exceptions as normal control flow।
Why ArrayDeque?
A strong general-purpose Queue implementation is:
ArrayDeque
Example:
Queue<String> queue =
new ArrayDeque<>();
ArrayDeque supports efficient operations at both ends।
For ordinary FIFO queues, it is usually a better default than manually using an ArrayList as a queue।
Why Not ArrayList?
Technically, you could write:
List<String> queue =
new ArrayList<>();
Add:
queue.add(
task
);
Then remove the first element:
queue.remove(
0
);
But removing index 0 from an ArrayList generally requires shifting later elements।
Conceptually:
[A, B, C, D]
remove A
[B, C, D]
↑ ↑ ↑
elements must shift
That makes it a poor default for repeated front-removal queue workloads।
Queue Expresses Intent
Compare:
List<String> tasks =
new ArrayList<>();
with:
Queue<String> tasks =
new ArrayDeque<>();
The second version tells another developer:
These values are processed in queue order.
Choosing the right collection is not only about performance।
It also communicates design intent।
Queue Order
A normal FIFO queue processes:
Insertion order
from the front।
Example:
queue.offer(
"A"
);
queue.offer(
"B"
);
queue.offer(
"C"
);
Then:
queue.poll()
returns:
A
Queue Does Not Mean Arbitrary Index Access
A queue is not designed around:
queue.get(5)
because the abstraction is not:
Random access by index
It is:
Process the next item
This is a major conceptual difference from List।
Queue Processing Pattern
One of the most common patterns is:
while (
!queue.isEmpty()
) {
T item =
queue.poll();
process(
item
);
}
Example:
while (
!tasks.isEmpty()
) {
String task =
tasks.poll();
System.out.println(
task
);
}
Using poll() Directly as the Condition
Another pattern:
String task;
while (
(
task = tasks.poll()
) != null
) {
System.out.println(
task
);
}
This is legal Java।
But for beginner and many production contexts, the assignment inside the condition is less obvious।
Prefer clarity:
while (
!tasks.isEmpty()
) {
String task =
tasks.poll();
process(
task
);
}
unless the alternative clearly improves the code।
Queue Size
Because Queue extends Collection, common operations are available:
queue.size()
queue.isEmpty()
queue.clear()
queue.contains(...)
Example:
System.out.println(
queue.size()
);
isEmpty()
Prefer:
queue.isEmpty()
over:
queue.size() == 0
because isEmpty() directly communicates the question being asked।
Queue Iteration
You can iterate over a queue:
for (
String task
: tasks
) {
System.out.println(
task
);
}
But this does not remove the elements।
Traversal and queue consumption are different operations।
Inspecting vs Consuming
Consider:
for (
String task
: tasks
) {
System.out.println(
task
);
}
After the loop:
Queue still contains the tasks.
But:
while (
!tasks.isEmpty()
) {
tasks.poll();
}
consumes them।
Queue Consumption Changes State
A queue is often a mutable workflow structure।
Example:
Before:
[A, B, C]
After:
queue.poll();
state becomes:
[B, C]
This mutation is part of the queue abstraction।
Example: Enrollment Processing
Suppose enrollment requests should be handled in arrival order।
Queue<String> enrollments =
new ArrayDeque<>();
enrollments.offer(
"Sakib"
);
enrollments.offer(
"Subu"
);
enrollments.offer(
"Sumu"
);
Processing:
while (
!enrollments.isEmpty()
) {
String learner =
enrollments.poll();
System.out.println(
"Enrolling: "
+ learner
);
}
Output:
Enrolling: Sakib
Enrolling: Subu
Enrolling: Sumu
Example: Support Requests
Imagine support requests arrive:
REQ-1001
REQ-1002
REQ-1003
A simple FIFO queue could be:
Queue<String> requests =
new ArrayDeque<>();
requests.offer(
"REQ-1001"
);
requests.offer(
"REQ-1002"
);
requests.offer(
"REQ-1003"
);
Next request:
requests.peek();
returns:
REQ-1001
Processing:
requests.poll();
removes:
REQ-1001
Backend Systems and Queues
The queue concept appears constantly in backend engineering।
Examples:
Background jobs
Email delivery
Payment processing
Event processing
Message brokers
Task scheduling
Request buffering
Batch processing
Java's in-memory Queue is not the same thing as a distributed message broker such as Kafka or RabbitMQ।
But the FIFO abstraction helps build the mental model।
In-Memory Queue vs Message Broker
An in-memory Java queue:
Queue<Task>
exists inside one running process।
If the process stops, that queue usually disappears unless separately persisted।
A message broker is a separate infrastructure component designed for concerns such as:
Durability
Distributed producers
Distributed consumers
Acknowledgement
Retries
Partitioning
Delivery guarantees
We are not teaching those systems here।
The important connection is simply:
Both can involve ordered work waiting to be processed.
FIFO Is Not Always Guaranteed Everywhere
Be careful with this statement:
Queue means FIFO
The Queue interface is used by multiple implementations, and some queues order elements differently।
For example:
PriorityQueue
does not process elements purely by insertion order।
It uses priority/natural ordering or a comparator।
We will study PriorityQueue later in the Algorithms module when discussing heaps।
For this lesson:
Queue + ArrayDeque
is our FIFO queue model।
Queue Is an Interface
This is worth reinforcing।
Queue<String> tasks =
new ArrayDeque<>();
The variable type:
Queue<String>
defines the operations we want to depend on।
Implementation:
ArrayDeque<String>
provides them।
This means code like:
static void processAll(
Queue<String> tasks
)
does not need to care whether a particular compatible implementation is used।
Passing a Queue to a Method
Example:
static void processAll(
Queue<String> tasks
) {
while (
!tasks.isEmpty()
) {
String task =
tasks.poll();
System.out.println(
"Processing: "
+ task
);
}
}
Call:
processAll(
tasks
);
Important: The Method Mutates the Queue
After:
processAll(
tasks
);
the queue is empty because poll() removed every element।
This should be intentional।
Read-Only Inspection Method
If you only want to inspect:
static void printAll(
Queue<String> tasks
) {
for (
String task
: tasks
) {
System.out.println(
task
);
}
}
This does not consume the queue।
Method Naming Should Reveal Mutation
Compare:
printAll(...)
with:
processAll(...)
processAll() suggests work may happen and queue state may change।
When a method consumes a collection, its contract should make that clear।
Queue of Custom Objects
Queues become much more useful once they store domain objects।
Example:
record Task(
long id,
String description
) {
}
Then:
Queue<Task> tasks =
new ArrayDeque<>();
Add:
tasks.offer(
new Task(
1,
"Generate certificate"
)
);
Process Domain Objects
Task task =
tasks.poll();
if (
task != null
) {
System.out.println(
task.description()
);
}
The queue controls processing order।
The object carries the actual domain data।
Example: Course Publication Jobs
record PublicationJob(
String courseCode
) {
}
Queue:
Queue<PublicationJob> jobs =
new ArrayDeque<>();
jobs.offer(
new PublicationJob(
"JAVA-OOP"
)
);
jobs.offer(
new PublicationJob(
"BACKEND-JAVA"
)
);
Processing:
while (
!jobs.isEmpty()
) {
PublicationJob job =
jobs.poll();
System.out.println(
"Publishing: "
+ job.courseCode()
);
}
Null Elements and ArrayDeque
ArrayDeque does not permit null elements।
This is useful because:
poll()
and:
peek()
use null to indicate that no element exists।
Therefore:
queue.offer(
null
);
with an ArrayDeque is invalid and results in a NullPointerException।
Why Null Rejection Helps
If null values were allowed:
queue.poll() == null
could mean either:
Queue was empty
or:
Queue contained a null item
Rejecting null keeps the semantics clear।
Queue and Duplicate Values
Queues can normally contain duplicate elements।
Example:
Queue<String> queue =
new ArrayDeque<>();
queue.offer(
"EMAIL"
);
queue.offer(
"EMAIL"
);
This is valid।
Unlike Set, a queue is not about uniqueness।
Its main concern is processing order।
Queue vs Set vs List
Think about the primary semantic question।
List
I need an ordered collection
and possibly index-based access.
Set
I need uniqueness.
Queue
I need items waiting to be processed
according to queue ordering.
Queue vs Map
A Map answers:
What value belongs to this key?
A Queue answers:
What item should be processed next?
These are fundamentally different abstractions।
Example: Breadth-First Processing Preview
Queues are especially important in algorithms involving:
Breadth-first traversal
For example, when processing a tree level by level:
Root
↓
Children
↓
Grandchildren
A queue keeps track of which node should be visited next।
We will study this idea later in algorithms/data structures।
Producer and Consumer Concept
A queue often creates a boundary between two roles:
Producer
Consumer
Producer adds work:
queue.offer(
task
);
Consumer removes work:
Task task =
queue.poll();
Conceptually:
Producer
↓
[ Queue ]
↓
Consumer
Simple Producer Example
static void submitTask(
Queue<String> tasks,
String task
) {
tasks.offer(
task
);
}
Simple Consumer Example
static String takeNextTask(
Queue<String> tasks
) {
return tasks.poll();
}
This model appears repeatedly in concurrent and distributed systems।
Later, concurrent queues add thread-safety concerns।
This Queue Is Not Automatically Thread-Safe
ArrayDeque itself is not designed as a thread-safe shared queue for concurrent mutation by multiple threads without coordination।
Later in Modern Java we will study structures such as:
BlockingQueue
ConcurrentLinkedQueue
and concurrency concepts properly।
For now, assume:
Single-threaded use
or externally controlled access
Common Beginner Mistake 1: Using remove(0) on ArrayList
For repeated FIFO processing:
list.remove(
0
);
is usually the wrong abstraction and can be inefficient।
Prefer:
Queue<T>
with an appropriate implementation।
Common Beginner Mistake 2: Confusing peek() with poll()
peek()
does not remove।
poll()
does।
Common Beginner Mistake 3: Expecting poll() to Throw on Empty Queue
queue.poll()
returns:
null
when empty।
If you want exception-based behavior:
queue.remove()
does that।
But exception-driven empty handling is usually unnecessary for normal queue consumption।
Common Beginner Mistake 4: Using remove() as a Normal Empty Check
Avoid patterns like:
try {
queue.remove();
} catch (...) {
// queue empty
}
when emptiness is expected।
Prefer:
poll()
or:
isEmpty()
depending on the use case।
Common Beginner Mistake 5: Assuming All Queue Implementations Are FIFO
PriorityQueue follows priority ordering।
Always understand the implementation semantics।
For FIFO:
ArrayDeque
is a strong choice।
Common Beginner Mistake 6: Iterating When You Intended to Consume
This:
for (
Task task
: queue
) {
process(
task
);
}
does not remove elements।
If the processing contract means completed work should leave the queue, use queue removal operations intentionally।
Common Beginner Mistake 7: Consuming a Queue Accidentally
If you pass a queue into:
processAll(
queue
);
and processAll() uses poll(), the caller's queue changes।
Remember:
Collections are mutable objects
and references are passed by value.
Both caller and method access the same queue object।
Common Beginner Mistake 8: Adding null
With:
ArrayDeque
do not insert null।
Use real domain values, or model absence separately।
Practical Example — Enrollment Request Queue
import java.util.ArrayDeque;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<String> enrollmentRequests =
new ArrayDeque<>();
submit(
enrollmentRequests,
"Sakib"
);
submit(
enrollmentRequests,
"Subu"
);
submit(
enrollmentRequests,
"Sumu"
);
System.out.println(
"Waiting: "
+ enrollmentRequests.size()
);
processNext(
enrollmentRequests
);
processNext(
enrollmentRequests
);
System.out.println(
"Next learner: "
+ enrollmentRequests.peek()
);
}
static void submit(
Queue<String> requests,
String learner
) {
requests.offer(
learner
);
}
static void processNext(
Queue<String> requests
) {
String learner =
requests.poll();
if (
learner == null
) {
System.out.println(
"No enrollment request."
);
return;
}
System.out.println(
"Processing enrollment for "
+ learner
);
}
}
Output:
Waiting: 3
Processing enrollment for Sakib
Processing enrollment for Subu
Next learner: Sumu
Practical Example — Task Queue
import java.util.ArrayDeque;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<Task> tasks =
new ArrayDeque<>();
tasks.offer(
new Task(
1,
"Send welcome email"
)
);
tasks.offer(
new Task(
2,
"Generate certificate"
)
);
tasks.offer(
new Task(
3,
"Update analytics"
)
);
processAll(
tasks
);
System.out.println(
"Remaining tasks: "
+ tasks.size()
);
}
static void processAll(
Queue<Task> tasks
) {
while (
!tasks.isEmpty()
) {
Task task =
tasks.poll();
System.out.println(
"Processing "
+ task.id()
+ ": "
+ task.description()
);
}
}
record Task(
long id,
String description
) {
}
}
Output:
Processing 1: Send welcome email
Processing 2: Generate certificate
Processing 3: Update analytics
Remaining tasks: 0
Practice 1 — Basic FIFO
Create a queue containing:
Java
Backend
System Design
Then remove and print every element।
Expected:
Java
Backend
System Design
Solution
Queue<String> courses =
new ArrayDeque<>();
courses.offer(
"Java"
);
courses.offer(
"Backend"
);
courses.offer(
"System Design"
);
while (
!courses.isEmpty()
) {
System.out.println(
courses.poll()
);
}
Practice 2 — Peek Without Removal
Given:
Queue<String> queue =
new ArrayDeque<>();
queue.offer(
"First"
);
queue.offer(
"Second"
);
Print the next element without removing it।
Solution
System.out.println(
queue.peek()
);
Queue still contains:
First
Second
Practice 3 — Empty Queue
What does this return?
Queue<String> queue =
new ArrayDeque<>();
String value =
queue.poll();
Answer
null
Practice 4 — Process Only One Item
Implement:
static String processNext(
Queue<String> queue
)
It should return the next value or:
"No work"
when empty।
Solution
static String processNext(
Queue<String> queue
) {
String value =
queue.poll();
if (
value == null
) {
return "No work";
}
return value;
}
Practice 5 — Count Without Consuming
Given a queue, count its elements without removing them।
Solution
Use:
queue.size()
There is no reason to consume the queue just to count it।
Practice 6 — Print Without Consuming
Implement:
static void printQueue(
Queue<String> queue
)
without removing values।
Solution
static void printQueue(
Queue<String> queue
) {
for (
String value
: queue
) {
System.out.println(
value
);
}
}
Practice 7 — Consume All
Implement:
static void clearByProcessing(
Queue<String> queue
)
that prints and removes every item।
Solution
static void clearByProcessing(
Queue<String> queue
) {
while (
!queue.isEmpty()
) {
String value =
queue.poll();
System.out.println(
value
);
}
}
Practice 8 — Predict the Output
Queue<Integer> numbers =
new ArrayDeque<>();
numbers.offer(
10
);
numbers.offer(
20
);
numbers.offer(
30
);
System.out.println(
numbers.poll()
);
System.out.println(
numbers.peek()
);
System.out.println(
numbers.poll()
);
Answer
10
20
20
After first poll():
[20, 30]
peek() sees 20 but does not remove it।
Second poll() removes 20।
Practice 9 — poll() vs remove()
What is the key empty-queue difference?
Answer
poll()
→ returns null
remove()
→ throws NoSuchElementException
Practice 10 — Choose the Collection
Which collection abstraction best matches each requirement?
A
Need unique course codes.
B
Need learner names in positional order with index access.
C
Need requests processed in arrival order.
Answers
A → Set
B → List
C → Queue
True or False
- FIFO means First In, First Out.
Queueis a concrete class.ArrayDequecan be used as a FIFO Queue.offer()adds an element.poll()removes the front element.peek()removes the front element.poll()returnsnullon an empty queue.remove()returnsnullon an empty queue.- Iterating over a queue automatically consumes it.
- Queues can contain duplicate values.
ArrayDequeallowsnullelements.- Every implementation of
Queuemust process strictly FIFO. - A Queue is often a better abstraction than
ArrayList.remove(0)for FIFO work. - Queue processing patterns appear in backend systems.
Answers
1. True
2. False
3. True
4. True
5. True
6. False
7. True
8. False
9. False
10. True
11. False
12. False
13. True
14. True
Knowledge Check
Question 1
What does FIFO mean?
Question 2
What is the primary purpose of a Queue?
Question 3
What does offer() do?
Question 4
What is the difference between poll() and peek()?
Question 5
What happens when poll() is called on an empty queue?
Question 6
What happens when remove() is called on an empty queue?
Question 7
Why is Queue<String> queue = new ArrayDeque<>() often preferable to declaring the variable as ArrayDeque<String>?
Question 8
Why is repeatedly removing index 0 from ArrayList not a strong default queue implementation?
Question 9
Does iterating over a queue remove elements?
Question 10
Why does ArrayDeque reject null?
Question 11
Are all Queue implementations FIFO?
Question 12
Give three backend-style situations where queue semantics are useful.
Knowledge Check Answers
Answer 1
FIFO means:
First In, First Out
The earliest inserted item is normally processed first।
Answer 2
A Queue models values waiting to be processed according to a queue-specific ordering policy।
Answer 3
offer() attempts to add an element to the queue।
Answer 4
peek() returns the next element without removing it, while poll() returns and removes it।
Answer 5
It returns:
null
Answer 6
It throws:
NoSuchElementException
Answer 7
Because the code depends on the queue abstraction rather than unnecessarily coupling callers to one particular implementation।
Answer 8
Removing the first ArrayList element generally requires shifting later elements, and List does not communicate FIFO-processing intent as clearly as Queue।
Answer 9
No।
Normal iteration only visits the elements।
Answer 10
Among other design reasons, this lets methods such as poll() and peek() use null unambiguously to represent an empty queue।
Answer 11
No।
For example:
PriorityQueue
uses priority-based ordering rather than simple FIFO insertion order।
Answer 12
Examples include:
Background jobs
Email processing
Task scheduling
Request buffering
Event processing
Lesson Summary
এই lesson-এ আমরা FIFO-style data processing এবং Java Queue abstraction শিখেছি।
We learned:
- FIFO means First In, First Out
Queue<E>models data waiting to be processedQueueis an interfaceArrayDequeis a strong general-purpose implementation for ordinary FIFO queuesoffer()adds an elementpoll()removes and returns the front elementpeek()inspects the front without removing itpoll()andpeek()returnnullfor an empty queueremove()andelement()use exception-based behavior on empty queues- Queue traversal does not automatically consume elements
- Queue-processing loops usually remove elements using
poll() - Queue operations mutate the queue state
- Queue parameters can be consumed by methods, so mutation should be intentional
ArrayDequedoes not permitnull- Queues can contain duplicate values
Queueexpresses processing intent better than treating aListas an improvised queue- Not every
Queueimplementation is strictly FIFO PriorityQueuewill be studied later with heap-based algorithms- Queue semantics appear naturally in backend jobs, request handling, scheduling, and messaging concepts
ArrayDequeitself is not automatically a thread-safe work queue
The core model is:
Producer
↓
offer()
↓
[ Queue ]
↓
poll()
↓
Consumer
For a normal FIFO queue:
First item added
↓
First item processed
Next Lesson
পরবর্তী নতুন lesson:
Deque, Stack, and ArrayDeque
আমরা শিখব:
- What a Deque is
- Adding and removing from both ends
addFirst()addLast()removeFirst()removeLast()peekFirst()peekLast()- Stack and LIFO behavior
push()pop()peek()- Why modern Java generally prefers
Dequeover legacyStack - Using
ArrayDequeas both Queue and Stack - Practical LIFO/FIFO use cases