Generics, Collections, and Core Data Structures

Iteration and Collection Operations

ReadingPreview

আপনি একটি free preview lesson দেখছেন।

Lesson Overview

Collection-এ data রাখা যথেষ্ট নয়। Real application-এ collection থেকে আমাদের প্রায়ই করতে হয়:

  • একটি element খুঁজে বের করা
  • Matching elements filter করা
  • Values transform করা
  • Total, count, average, minimum বা maximum বের করা
  • Duplicate বা invalid elements remove করা
  • Values group করা
  • Repeated lookup efficient করা

এই lesson-এ আমরা List, Set, এবং Map-এর ওপর common processing patterns শিখব।


Learning Objectives

এই lesson শেষে আপনি পারবেন:

  • Appropriate loop নির্বাচন করতে
  • Safeভাবে collection iterate করতে
  • Iteration-এর সময় element remove করতে
  • Search, filter এবং transform operations লিখতে
  • Aggregation perform করতে
  • Map দিয়ে counting এবং grouping করতে
  • Nested loop-এর cost বুঝতে
  • Collection-processing code readable রাখতে

Choosing an Iteration Style

Java-তে collection iterate করার common approaches:

Enhanced for loop
Index-based loop
Iterator
Map entry iteration

সব operation-এর জন্য একই approach best নয়।

Simple rule:

Operation-এর জন্য যতটুকু control দরকার, ততটুকু control দেয় এমন সবচেয়ে simple iteration style ব্যবহার করুন।


Enhanced for Loop

যখন প্রতিটি element read বা process করতে হবে এবং index প্রয়োজন নেই:

for (
        Course course
        : courses
) {
    System.out.println(
            course.getTitle()
    );
}

Use enhanced for when:

  • Every element process করতে হবে
  • Position প্রয়োজন নেই
  • Collection structure modify করা হবে না

এটি সাধারণত সবচেয়ে readable option।


Index-Based Loop

Index প্রয়োজন হলে:

for (
        int index = 0;
        index < lessons.size();
        index++
) {
    Lesson lesson =
            lessons.get(
                    index
            );

    System.out.println(
            (index + 1)
            + ". "
            + lesson.getTitle()
    );
}

Use index loop when:

  • Element position প্রয়োজন
  • Existing element replace করতে হবে
  • Specific index remove করতে হবে
  • Previous বা next element compare করতে হবে

Always use:

index < list.size()

Not:

index <= list.size()

কারণ size() valid index নয়।

Last valid index:

size() - 1

Iterator

Iterator<E> collection traverse করার explicit mechanism।

import java.util.Iterator;
Iterator<String> iterator =
        names.iterator();

while (
        iterator.hasNext()
) {
    String name =
            iterator.next();

    System.out.println(
            name
    );
}

Important methods:

hasNext()
next()
remove()

Safe Removal During Iteration

Enhanced for loop-এর মধ্যে direct removal unsafe হতে পারে।

for (
        String name
        : names
) {
    if (
            name == null
            || name.isBlank()
    ) {
        names.remove(
                name
        );
    }
}

এটি runtime-এ তৈরি করতে পারে:

ConcurrentModificationException

কারণ active iteration-এর বাইরে collection structure change করা হচ্ছে।


Removing with Iterator

Iterator<String> iterator =
        names.iterator();

while (
        iterator.hasNext()
) {
    String name =
            iterator.next();

    if (
            name == null
            || name.isBlank()
    ) {
        iterator.remove();
    }
}

iterator.remove() active iterator-এর মাধ্যমে current element safely remove করে।

You must call:

next()

before:

remove()

Otherwise:

IllegalStateException

হতে পারে।


Removal with an Index Loop

for (
        int index = 0;
        index < names.size();
) {
    String name =
            names.get(
                    index
            );

    if (
            name == null
            || name.isBlank()
    ) {
        names.remove(
                index
        );
    } else {
        index++;
    }
}

Removal-এর পরে next element একই index-এ shift হয়।

তাই remove করলে immediately index++ করা হয়নি।


The Skipped Element Bug

Suppose:

["", "", "Subu"]

Wrong:

for (
        int index = 0;
        index < names.size();
        index++
) {
    if (
            names.get(
                    index
            ).isBlank()
    ) {
        names.remove(
                index
        );
    }
}

First blank remove হওয়ার পরে second blank index 0-এ shift হয়।

Loop index 1 হয়ে যাওয়ায় second blank skip হয়ে যায়।

Possible result:

["", "Subu"]

removeIf()

Simple condition হলে:

names.removeIf(
        name ->
                name == null
                || name.isBlank()
);

Meaning:

Condition true হলে element remove করো

এটি lambda ব্যবহার করে। Lambdas পরে formally শেখানো হবে।


Searching for an Element

public static Course findCourseById(
        List<Course> courses,
        long courseId
) {
    if (courses == null) {
        return null;
    }

    for (
            Course course
            : courses
    ) {
        if (
                course != null
                && course.getId()
                == courseId
        ) {
            return course;
        }
    }

    return null;
}

Match পাওয়া মাত্র:

return course;

method exit করে।

এটিকে early return বলা যায়।


Why Early Return Is Useful

Weak:

Course found =
        null;

for (
        Course course
        : courses
) {
    if (
            course.getId()
            == courseId
    ) {
        found = course;
    }
}

return found;

Problems:

  • Match পাওয়ার পরও loop continue করে
  • Duplicate থাকলে last match return হতে পারে
  • Extra mutable variable প্রয়োজন

Better:

return course;

as soon as the result is known।


break

break nearest loop থেকে বের হয়।

Course found =
        null;

for (
        Course course
        : courses
) {
    if (
            course.getId()
            == courseId
    ) {
        found = course;

        break;
    }
}

Difference:

break  → Loop থেকে বের হয়
return → Entire method থেকে বের হয়

Method-এর loop-এর পরে আরও কাজ থাকলে break useful।


continue

continue current iteration skip করে।

for (
        Course course
        : courses
) {
    if (course == null) {
        continue;
    }

    if (!course.isPublished()) {
        continue;
    }

    System.out.println(
            course.getTitle()
    );
}

এতে deeply nested if block কমে।


Checking Whether Any Element Matches

public static boolean hasPublishedCourse(
        List<Course> courses
) {
    if (courses == null) {
        return false;
    }

    for (
            Course course
            : courses
    ) {
        if (
                course != null
                && course.isPublished()
        ) {
            return true;
        }
    }

    return false;
}

First match-এর পর processing শেষ।


Checking Whether All Elements Match

public static boolean areAllCoursesPublished(
        List<Course> courses
) {
    if (
            courses == null
            || courses.isEmpty()
    ) {
        return false;
    }

    for (
            Course course
            : courses
    ) {
        if (
                course == null
                || !course.isPublished()
        ) {
            return false;
        }
    }

    return true;
}

First invalid element-এর পর method false return করে।


Filtering

Filtering means:

Source collection থেকে condition matching elements নিয়ে new collection তৈরি করা।

public static List<Course> findPublishedCourses(
        List<Course> courses
) {
    if (courses == null) {
        return List.of();
    }

    List<Course> publishedCourses =
            new ArrayList<>();

    for (
            Course course
            : courses
    ) {
        if (
                course != null
                && course.isPublished()
        ) {
            publishedCourses.add(
                    course
            );
        }
    }

    return List.copyOf(
            publishedCourses
    );
}

Source collection unchanged থাকে।


Filter or Mutate?

Suppose unpublished courses বাদ দিতে হবে।

Two meanings possible:

Create a Selected Result

findPublishedCourses(...)

Source unchanged।

Modify Owned State

removeUnpublishedCourses(...)

Source changes।

Method name operation-এর intent clear করা উচিত।

A method named:

findPublishedCourses()

should not silently remove items from the input collection।


Transformation

Transformation means:

প্রতিটি source element থেকে another value তৈরি করা।

Example:

public static List<String> extractCourseTitles(
        List<Course> courses
) {
    if (courses == null) {
        return List.of();
    }

    List<String> titles =
            new ArrayList<>();

    for (
            Course course
            : courses
    ) {
        if (course == null) {
            continue;
        }

        titles.add(
                course.getTitle()
        );
    }

    return List.copyOf(
            titles
    );
}

Input:

List<Course>

Output:

List<String>

Filtering and Transformation Together

public static List<String> findPublishedTitles(
        List<Course> courses
) {
    if (courses == null) {
        return List.of();
    }

    List<String> titles =
            new ArrayList<>();

    for (
            Course course
            : courses
    ) {
        if (
                course == null
                || !course.isPublished()
        ) {
            continue;
        }

        titles.add(
                course.getTitle()
        );
    }

    return List.copyOf(
            titles
    );
}

The loop:

  1. Unpublished courses filter করে
  2. Matching coursesকে title-এ transform করে

Aggregation

Aggregation multiple values combine করে one result তৈরি করে।

Examples:

Total price
Total duration
Published course count
Average score
Maximum price
Minimum price

Calculating a Total

public static long calculateTotalPrice(
        List<Course> courses
) {
    long total =
            0L;

    if (courses == null) {
        return total;
    }

    for (
            Course course
            : courses
    ) {
        if (course == null) {
            continue;
        }

        total +=
                course.getPriceInPaisa();
    }

    return total;
}

total হলো accumulator।


Counting Matching Elements

public static int countPublishedCourses(
        List<Course> courses
) {
    int count =
            0;

    if (courses == null) {
        return count;
    }

    for (
            Course course
            : courses
    ) {
        if (
                course != null
                && course.isPublished()
        ) {
            count++;
        }
    }

    return count;
}

Calculating an Average

public static double calculateAveragePrice(
        List<Course> courses
) {
    if (
            courses == null
            || courses.isEmpty()
    ) {
        return 0.0;
    }

    long total =
            0L;

    int validCount =
            0;

    for (
            Course course
            : courses
    ) {
        if (course == null) {
            continue;
        }

        total +=
                course.getPriceInPaisa();

        validCount++;
    }

    if (validCount == 0) {
        return 0.0;
    }

    return (double) total
            / validCount;
}

Cast required:

(double) total

Without it:

5 / 2

becomes:

2

not:

2.5

Finding a Maximum

public static Course findMostExpensiveCourse(
        List<Course> courses
) {
    if (courses == null) {
        return null;
    }

    Course mostExpensive =
            null;

    for (
            Course course
            : courses
    ) {
        if (course == null) {
            continue;
        }

        if (
                mostExpensive == null
                || course.getPriceInPaisa()
                > mostExpensive
                        .getPriceInPaisa()
        ) {
            mostExpensive =
                    course;
        }
    }

    return mostExpensive;
}

First valid course initial candidate হয়।

This is better than:

long maximum =
        0L;

কারণ valid values সবসময় non-negative হবে—এমন assumption generic algorithms-এ safe নয়।


Finding a Minimum

public static Course findCheapestCourse(
        List<Course> courses
) {
    if (courses == null) {
        return null;
    }

    Course cheapest =
            null;

    for (
            Course course
            : courses
    ) {
        if (course == null) {
            continue;
        }

        if (
                cheapest == null
                || course.getPriceInPaisa()
                < cheapest.getPriceInPaisa()
        ) {
            cheapest =
                    course;
        }
    }

    return cheapest;
}

Counting Values with Map

Input:

JAVA
BACKEND
JAVA
SPRING
BACKEND
JAVA

Desired result:

JAVA    → 3
BACKEND → 2
SPRING  → 1

Implementation:

public static Map<String, Integer> countTags(
        List<String> tags
) {
    if (tags == null) {
        return Map.of();
    }

    Map<String, Integer> counts =
            new HashMap<>();

    for (
            String tag
            : tags
    ) {
        if (
                tag == null
                || tag.isBlank()
        ) {
            continue;
        }

        String normalizedTag =
                tag.strip()
                        .toUpperCase();

        int currentCount =
                counts.getOrDefault(
                        normalizedTag,
                        0
                );

        counts.put(
                normalizedTag,
                currentCount + 1
        );
    }

    return Map.copyOf(
            counts
    );
}

Why Use getOrDefault()?

For first occurrence:

counts.getOrDefault(
        "JAVA",
        0
)

returns:

0

Then:

counts.put(
        "JAVA",
        1
);

Next occurrence returns current count 1, then stores 2


Grouping Values

Grouping means:

Valuesকে shared key অনুযায়ী collections-এ organize করা।

Example:

Difficulty → Courses

Type:

Map<String, List<Course>>

Manual Grouping

public static Map<String, List<Course>> groupByDifficulty(
        List<Course> courses
) {
    if (courses == null) {
        return Map.of();
    }

    Map<String, List<Course>> groups =
            new HashMap<>();

    for (
            Course course
            : courses
    ) {
        if (course == null) {
            continue;
        }

        String difficulty =
                course.getDifficulty();

        List<Course> group =
                groups.get(
                        difficulty
                );

        if (group == null) {
            group =
                    new ArrayList<>();

            groups.put(
                    difficulty,
                    group
            );
        }

        group.add(
                course
        );
    }

    return createImmutableGroups(
            groups
    );
}

Protecting Nested Collections

Only this is not enough:

return Map.copyOf(
        groups
);

Outer map immutable হলেও inner lists mutable থাকতে পারে।

Safer:

private static Map<String, List<Course>> createImmutableGroups(
        Map<String, List<Course>> groups
) {
    Map<String, List<Course>> copy =
            new HashMap<>();

    for (
            Map.Entry<String, List<Course>> entry
            : groups.entrySet()
    ) {
        copy.put(
                entry.getKey(),
                List.copyOf(
                        entry.getValue()
                )
        );
    }

    return Map.copyOf(
            copy
    );
}

This protects:

Outer map structure
Inner list structures

The Course objects themselves may still be mutable।


Iterating Over a Map

Only keys needed:

for (
        CourseCode code
        : coursesByCode.keySet()
) {
}

Only values needed:

for (
        Course course
        : coursesByCode.values()
) {
}

Both key and value needed:

for (
        Map.Entry<CourseCode, Course> entry
        : coursesByCode.entrySet()
) {
    CourseCode code =
            entry.getKey();

    Course course =
            entry.getValue();
}

Use entrySet() when both are needed।


Removing Map Entries Safely

Unsafe:

for (
        CourseCode code
        : coursesByCode.keySet()
) {
    if (
            shouldRemove(
                    code
            )
    ) {
        coursesByCode.remove(
                code
        );
    }
}

Safer:

Iterator<Map.Entry<CourseCode, Course>> iterator =
        coursesByCode
                .entrySet()
                .iterator();

while (
        iterator.hasNext()
) {
    Map.Entry<CourseCode, Course> entry =
            iterator.next();

    if (
            !entry.getValue()
                    .isPublished()
    ) {
        iterator.remove();
    }
}

Nested Iteration

for (
        Learner learner
        : learners
) {
    for (
            Course course
            : courses
    ) {
        checkEligibility(
                learner,
                course
        );
    }
}

If there are:

100 learners
50 courses

operations:

5,000 comparisons

Nested loops are not automatically wrong।

If every learner must genuinely be compared with every course, this is appropriate।


Accidental Repeated Search

Suppose:

List<Course> courses
List<CourseCode> requestedCodes

Weak:

for (
        CourseCode requestedCode
        : requestedCodes
) {
    for (
            Course course
            : courses
    ) {
        if (
                course.getCode()
                        .equals(
                                requestedCode
                        )
        ) {
            // Found
        }
    }
}

Every requested code scans all courses।


Build a Lookup Map

Map<CourseCode, Course> coursesByCode =
        new HashMap<>();

for (
        Course course
        : courses
) {
    coursesByCode.put(
            course.getCode(),
            course
    );
}

Then:

for (
        CourseCode requestedCode
        : requestedCodes
) {
    Course course =
            coursesByCode.get(
                    requestedCode
            );

    if (course != null) {
        // Found
    }
}

Repeated key lookup-এর জন্য Map data structure operation-এর সঙ্গে better match করে।


Performance Is More Than Loop Syntax

A simple loop can still be expensive:

for (
        Course course
        : courses
) {
    int enrollmentCount =
            loadEnrollmentCountFromDatabase(
                    course.getId()
            );
}

If there are 100 courses, this may cause 100 database calls।

This is often known as an:

N+1 query problem

Possible better design:

  • Load counts in one batch
  • Use a query that returns all required data
  • Build a lookup map once

Work inside the loop often matters more than loop syntax।


Do Not Combine Too Many Responsibilities

Weak:

for (
        Course course
        : courses
) {
    totalPrice +=
            course.getPriceInPaisa();

    if (course.isPublished()) {
        publishedCourses.add(
                course
        );
    }

    notificationSender.send(...);
    auditLogger.log(...);
}

This loop mixes:

  • Aggregation
  • Filtering
  • External notification
  • Logging

One pass may look efficient, but code becomes harder to test and reason about।

Prefer focused operations unless measurement proves combining them is necessary।


Side Effects During Iteration

A loop sending notifications may fail halfway:

First 5 notifications sent
6th failed
Remaining notifications not sent

Collection iteration itself does not provide:

  • Transaction
  • Retry
  • Rollback
  • Idempotency
  • Failure recovery

For side-effecting batch operations, failure behavior must be designed deliberately।


Complete Example

Course.java

public final class Course {

    private final long id;
    private final String title;
    private final String difficulty;
    private final long priceInPaisa;

    private boolean published;

    public Course(
            long id,
            String title,
            String difficulty,
            long priceInPaisa,
            boolean published
    ) {
        if (id <= 0) {
            throw new IllegalArgumentException(
                    "Course ID must be positive."
            );
        }

        if (
                title == null
                || title.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Course title is required."
            );
        }

        if (
                difficulty == null
                || difficulty.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Difficulty is required."
            );
        }

        if (priceInPaisa < 0) {
            throw new IllegalArgumentException(
                    "Price cannot be negative."
            );
        }

        this.id = id;
        this.title = title.strip();

        this.difficulty =
                difficulty.strip()
                        .toUpperCase();

        this.priceInPaisa =
                priceInPaisa;

        this.published =
                published;
    }

    public long getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

    public String getDifficulty() {
        return difficulty;
    }

    public long getPriceInPaisa() {
        return priceInPaisa;
    }

    public boolean isPublished() {
        return published;
    }
}

CourseOperations.java

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class CourseOperations {

    private CourseOperations() {
    }

    public static List<Course> findPublishedCourses(
            List<Course> courses
    ) {
        if (courses == null) {
            return List.of();
        }

        List<Course> result =
                new ArrayList<>();

        for (
                Course course
                : courses
        ) {
            if (
                    course != null
                    && course.isPublished()
            ) {
                result.add(
                        course
                );
            }
        }

        return List.copyOf(
                result
        );
    }

    public static List<String> extractTitles(
            List<Course> courses
    ) {
        if (courses == null) {
            return List.of();
        }

        List<String> titles =
                new ArrayList<>();

        for (
                Course course
                : courses
        ) {
            if (course == null) {
                continue;
            }

            titles.add(
                    course.getTitle()
            );
        }

        return List.copyOf(
                titles
        );
    }

    public static long calculateTotalPrice(
            List<Course> courses
    ) {
        long total =
                0L;

        if (courses == null) {
            return total;
        }

        for (
                Course course
                : courses
        ) {
            if (course != null) {
                total +=
                        course.getPriceInPaisa();
            }
        }

        return total;
    }

    public static Course findMostExpensive(
            List<Course> courses
    ) {
        if (courses == null) {
            return null;
        }

        Course mostExpensive =
                null;

        for (
                Course course
                : courses
        ) {
            if (course == null) {
                continue;
            }

            if (
                    mostExpensive == null
                    || course.getPriceInPaisa()
                    > mostExpensive
                            .getPriceInPaisa()
            ) {
                mostExpensive =
                        course;
            }
        }

        return mostExpensive;
    }

    public static Map<String, Integer> countByDifficulty(
            List<Course> courses
    ) {
        if (courses == null) {
            return Map.of();
        }

        Map<String, Integer> counts =
                new HashMap<>();

        for (
                Course course
                : courses
        ) {
            if (course == null) {
                continue;
            }

            String difficulty =
                    course.getDifficulty();

            counts.put(
                    difficulty,
                    counts.getOrDefault(
                            difficulty,
                            0
                    ) + 1
            );
        }

        return Map.copyOf(
                counts
        );
    }
}

Main.java

import java.util.List;
import java.util.Map;

public class Main {

    public static void main(
            String[] args
    ) {
        List<Course> courses =
                List.of(
                        new Course(
                                1L,
                                "Java and OOP Foundation",
                                "BEGINNER",
                                499_000L,
                                true
                        ),
                        new Course(
                                2L,
                                "Backend Development",
                                "INTERMEDIATE",
                                899_000L,
                                true
                        ),
                        new Course(
                                3L,
                                "System Design",
                                "ADVANCED",
                                1_299_000L,
                                false
                        ),
                        new Course(
                                4L,
                                "Programming Basics",
                                "BEGINNER",
                                0L,
                                true
                        )
                );

        List<Course> publishedCourses =
                CourseOperations
                        .findPublishedCourses(
                                courses
                        );

        System.out.println(
                "Published titles:"
        );

        for (
                String title
                : CourseOperations
                        .extractTitles(
                                publishedCourses
                        )
        ) {
            System.out.println(
                    title
            );
        }

        System.out.println(
                "Total price: "
                + CourseOperations
                        .calculateTotalPrice(
                                courses
                        )
        );

        Course mostExpensive =
                CourseOperations
                        .findMostExpensive(
                                courses
                        );

        if (mostExpensive != null) {
            System.out.println(
                    "Most expensive: "
                    + mostExpensive.getTitle()
            );
        }

        Map<String, Integer> counts =
                CourseOperations
                        .countByDifficulty(
                                courses
                        );

        System.out.println(
                "Difficulty counts: "
                + counts
        );
    }
}

Possible output:

Published titles:
Java and OOP Foundation
Backend Development
Programming Basics
Total price: 2697000
Most expensive: System Design
Difficulty counts: {BEGINNER=2, INTERMEDIATE=1, ADVANCED=1}

HashMap-based result-এর printed order vary করতে পারে।


Common Mistakes

Removing Inside Enhanced for

Can produce:

ConcurrentModificationException

Calling Iterator.remove() Before next()

Can produce:

IllegalStateException

Using <= size()

Attempts to access an invalid index।


Incrementing Index Immediately After Removal

Can skip the shifted next element।


Continuing Search After Match

Wastes work and may return the wrong duplicate।


Mutating Caller-Owned Collection in a Search Method

Method behavior becomes surprising।


Returning Mutable Working Collections

Caller can change result structure unexpectedly।


Calculating Average with Integer Division

Produces truncated result।


Initializing Maximum with an Arbitrary Value

May fail for valid negative or unusual ranges।


Protecting Only the Outer Group Map

Inner lists may still be mutable।


Using Nested Loops for Frequent Key Lookup

A Map may be more appropriate।


Performing Database or Network Calls in Every Iteration

Can create serious performance and partial-failure problems।


Practice Exercises

Exercise 1: Safe Removal

Given:

List<String> names

Remove:

  • null
  • Blank values
  • Values shorter than three characters

Use Iterator


Exercise 2: Search

Write:

static Learner findLearnerById(
        List<Learner> learners,
        long learnerId
)

Requirements:

  • Ignore null elements
  • Return immediately after match
  • Return null when absent

Exercise 3: Filter

Write:

static List<Course> findFreeCourses(
        List<Course> courses
)

Requirements:

  • Price must be zero
  • Source list unchanged
  • Immutable result
  • Null source returns empty list

Exercise 4: Transform

Write:

static List<Long> extractCourseIds(
        List<Course> courses
)

Ignore null courses।


Exercise 5: Aggregate

Given:

List<ContentItem>

Calculate total estimated minutes using polymorphism।


Exercise 6: Count

Given:

ACTIVE
CANCELLED
ACTIVE
PENDING
ACTIVE

Create:

Map<String, Integer>

Expected:

ACTIVE    → 3
CANCELLED → 1
PENDING   → 1

Exercise 7: Group

Create:

Map<Long, List<Course>>

where key is instructor ID।

Protect both outer map and inner lists।


Exercise 8: Improve Lookup

Given:

List<Course> courses
List<Long> requestedCourseIds

Replace repeated nested search with:

Map<Long, Course>

Explain why it improves repeated lookup।


Predict the Result

Question 1

List<String> values =
        new ArrayList<>(
                List.of(
                        "",
                        "",
                        "Subu"
                )
        );

for (
        int index = 0;
        index < values.size();
        index++
) {
    if (
            values.get(
                    index
            ).isBlank()
    ) {
        values.remove(
                index
        );
    }
}

System.out.println(
        values
);

Answer

[, Subu]

One shifted blank was skipped।


Question 2

Iterator<String> iterator =
        values.iterator();

iterator.remove();

Answer

May throw:

IllegalStateException

because next() was not called first।


Question 3

long total =
        5L;

int count =
        2;

double average =
        total
        / count;

Answer

2.0

Integer division happens before assignment to double


Question 4

double average =
        (double) total
        / count;

Answer

2.5

Question 5

Map<String, Integer> counts =
        new HashMap<>();

counts.put(
        "JAVA",
        counts.getOrDefault(
                "JAVA",
                0
        ) + 1
);

Answer

JAVA → 1

Knowledge Check

Question 1

Enhanced for কখন appropriate?

Question 2

Index loop কখন প্রয়োজন?

Question 3

Iterator-এর core methods কী?

Question 4

Direct removal during enhanced for unsafe কেন?

Question 5

Filtering কী?

Question 6

Transformation কী?

Question 7

Aggregation কী?

Question 8

Early return useful কেন?

Question 9

break এবং return-এর difference কী?

Question 10

Frequency count-এর জন্য Map suitable কেন?

Question 11

Nested group result protect করতে কী copy করতে হয়?

Question 12

Nested loop সবসময় wrong কি?

Question 13

Repeated key lookup-এর জন্য কোন collection useful?

Question 14

Expensive external call loop-এর মধ্যে problematic কেন?


Knowledge Check Answers

Answer 1

Index ছাড়া every element read বা process করতে হলে।

Answer 2

Position, replacement, neighbor access, numbering, অথবা index-based removal প্রয়োজন হলে।

Answer 3

hasNext(), next(), এবং remove()

Answer 4

Collection structure active iterator-এর বাইরে change হয় এবং fail-fast exception হতে পারে।

Answer 5

Condition matching elements নিয়ে new collection তৈরি করা।

Answer 6

Source elementsকে another representation-এ convert করা।

Answer 7

Multiple values combine করে one result তৈরি করা।

Answer 8

Match পাওয়া মাত্র unnecessary processing বন্ধ হয় এবং logic simpler থাকে।

Answer 9

break nearest loop exit করে; return entire method exit করে।

Answer 10

Each distinct value unique key এবং count associated value হতে পারে।

Answer 11

Outer map এবং each inner collection structure।

Answer 12

না। Every combination genuinely required হলে appropriate।

Answer 13

Map

Answer 14

Every iteration network, database, or file operation repeat করে total cost এবং failure risk বাড়ায়।


Lesson Summary

এই lesson-এ আমরা শিখেছি:

  • Iteration style operation-এর needs অনুযায়ী choose করতে হয়
  • Enhanced for read-only processing-এর জন্য clear
  • Index loop position-aware logic-এর জন্য useful
  • Iterator explicit traversal এবং safe removal support করে
  • Iterator.remove()-এর আগে next() call করতে হয়
  • Enhanced for-এ direct structural mutation unsafe
  • Removal-এর পরে shifted index carefully handle করতে হয়
  • Early return search logic simplify করে
  • break loop exit করে, return method exit করে
  • continue irrelevant iteration skip করে
  • Filtering selected values দিয়ে new collection তৈরি করে
  • Transformation source valuesকে another type-এ convert করে
  • Aggregation total, count, average, minimum এবং maximum তৈরি করে
  • Average calculation-এ floating-point division প্রয়োজন
  • Maximum/minimum first valid element দিয়ে initialize করা safer
  • Map frequency counting-এর জন্য natural
  • Grouping Map<K, List<V>> বা Map<K, Set<V>> ব্যবহার করতে পারে
  • Nested immutable results outer এবং inner collections দুটো protect করে
  • Repeated key lookup Map দিয়ে improve করা যায়
  • Nested loops automatically wrong নয়
  • Expensive calls inside loops hidden performance problems তৈরি করতে পারে
  • Collection operations focused এবং clearly named হওয়া উচিত

Next Lesson

পরবর্তী lesson:

Designing Classes That Own Collections

আমরা শিখব:

  • Aggregate object
  • Internal mutable collections
  • Defensive copying
  • Controlled add, update, and remove operations
  • Collection invariants
  • Duplicate prevention
  • Ordering rules
  • Maximum size rules
  • Read-only snapshots
  • Avoiding leaked mutable state
  • Designing a complete Course that owns lessons