Generics, Collections, and Core Data Structures
Working with `Set`
You are viewing a free preview lesson.
Lesson Overview
আগের lesson-এ আমরা List শিখেছি।
List useful যখন:
- Element order গুরুত্বপূর্ণ
- Index দিয়ে access করতে হবে
- Duplicate values গ্রহণযোগ্য
- Sequence business meaning বহন করে
কিন্তু কিছু data naturally unique।
Examples:
Course codes
User roles
Supported languages
Unique learner enrollments
Completed lesson IDs
Applied coupon codes
একজন learner একই course-এ দুইবার enrolled হওয়া উচিত নয়।
একটি course catalog-এ একই course code দুইবার থাকা উচিত নয়।
এ ধরনের requirement-এর জন্য Java provides:
Set<E>
Set:
- Duplicate elements রাখে না
- Index-based নয়
- Equality-এর মাধ্যমে duplicate detect করে
- Mutable বা immutable হতে পারে
- Different ordering behavior-এর implementations থাকতে পারে
Common mutable implementation:
HashSet<E>
এই lesson-এ আমরা শিখব:
SetকীHashSet- Unique element insertion
add()-এর return value- Searching এবং removal
- Set iteration
- Ordering guarantees
Set.of()এবংSet.copyOf()equals()এবংhashCode()- Custom objects-এর uniqueness
- Mutable set elements-এর risk
ListবনামSet- Unique enrollment registry design
Learning Objectives
এই lesson শেষ করার পর আপনি পারবেন:
Setdeclare এবং initialize করতেHashSetব্যবহার করতে- Duplicate insertion detect করতে
contains()এবংremove()ব্যবহার করতে- Set safely iterate করতে
HashSetordering-এর limitation বুঝতেSet.of()এবংSet.copyOf()ব্যবহার করতেequals()এবংhashCode()uniqueness-এ কীভাবে কাজ করে explain করতে- Custom immutable set element design করতে
- Mutable hash-based element-এর risk identify করতে
ListএবংSet-এর মধ্যে appropriate choice নিতে
What Is a Set?
Set একটি collection যা duplicate elements রাখে না।
Set<String> courseCodes =
new HashSet<>();
Add:
courseCodes.add(
"JAVA-OOP"
);
courseCodes.add(
"BACKEND"
);
courseCodes.add(
"JAVA-OOP"
);
Set-এর content থাকবে:
JAVA-OOP
BACKEND
Second "JAVA-OOP" আলাদা duplicate element হিসেবে add হবে না।
Importing Set and HashSet
import java.util.HashSet;
import java.util.Set;
Declaration:
Set<String> values =
new HashSet<>();
Variable type:
Set<String>
Implementation:
HashSet<String>
Set interface-এর ওপর depend করলে implementation detail unnecessaryভাবে expose হয় না।
Creating an Empty Mutable Set
Set<String> supportedLanguages =
new HashSet<>();
Initially:
supportedLanguages.isEmpty()
returns:
true
And:
supportedLanguages.size()
returns:
0
Adding Elements
Use:
add(E element)
Example:
supportedLanguages.add(
"BN"
);
supportedLanguages.add(
"EN"
);
supportedLanguages.add(
"ET"
);
Set now contains three unique elements।
add() Returns Whether the Set Changed
Set.add()-এর return value খুব useful।
boolean added =
supportedLanguages.add(
"BN"
);
First insertion:
true
Add same value again:
boolean addedAgain =
supportedLanguages.add(
"BN"
);
Result:
false
কারণ set already "BN" contains করে।
Set change হয়নি।
Using add() for Duplicate Detection
public static boolean registerCourseCode(
Set<String> courseCodes,
String courseCode
) {
if (
courseCodes == null
|| courseCode == null
|| courseCode.isBlank()
) {
return false;
}
return courseCodes.add(
courseCode.strip()
.toUpperCase()
);
}
Usage:
Set<String> courseCodes =
new HashSet<>();
System.out.println(
registerCourseCode(
courseCodes,
"java-oop"
)
);
System.out.println(
registerCourseCode(
courseCodes,
"JAVA-OOP"
)
);
Output:
true
false
Normalization-এর কারণে দুইটি input একই logical code হিসেবে treated হয়েছে।
Uniqueness Depends on Equality
Set duplicate decide করে values logically equal কি না।
For String:
"JAVA".equals(
"JAVA"
)
returns:
true
তাই second "JAVA" duplicate।
But:
"JAVA".equals(
"java"
)
returns:
false
So without normalization:
Set<String> codes =
new HashSet<>();
codes.add(
"JAVA"
);
codes.add(
"java"
);
Set দুইটি values রাখতে পারে।
Domain-level normalization এখনও application responsibility।
Set Has No Index
A Set is not index-based।
Invalid:
courseCodes.get(
0
);
Set interface-এ get() method নেই।
Also no:
set(
index,
value
)
কারণ set element position contract-এর অংশ নয়।
If position matters, use List।
Checking Whether a Value Exists
boolean supportsBangla =
supportedLanguages.contains(
"BN"
);
Result:
true
If value absent:
supportedLanguages.contains(
"DE"
);
returns:
false
contains() equality rules use করে।
Removing an Element
boolean removed =
supportedLanguages.remove(
"ET"
);
If value existed:
true
If absent:
false
Unlike List, Set.remove() index-based overload expose করে না।
remove(value)
means element value remove করা।
Set Size
int languageCount =
supportedLanguages.size();
Duplicate insertion size increase করে না।
Set<String> values =
new HashSet<>();
values.add(
"JAVA"
);
values.add(
"JAVA"
);
System.out.println(
values.size()
);
Output:
1
Clearing a Set
supportedLanguages.clear();
After clearing:
supportedLanguages.isEmpty()
returns:
true
Domain object-এর internal set direct clear করা business rules bypass করতে পারে।
Controlled methods prefer করুন।
Adding Multiple Elements
Set<String> primaryLanguages =
new HashSet<>();
primaryLanguages.add(
"BN"
);
Set<String> additionalLanguages =
Set.of(
"EN",
"ET"
);
primaryLanguages.addAll(
additionalLanguages
);
Result contains:
BN
EN
ET
Existing duplicates add হলেও set size বাড়বে না।
Removing Multiple Elements
supportedLanguages.removeAll(
Set.of(
"ET",
"DE"
)
);
Matching elements remove হয়।
Missing values harmless।
Keeping Common Elements
Set<String> instructorLanguages =
new HashSet<>(
Set.of(
"BN",
"EN",
"ET"
)
);
Set<String> learnerLanguages =
Set.of(
"BN",
"FI"
);
instructorLanguages.retainAll(
learnerLanguages
);
Result:
BN
retainAll() শুধু common elements রাখে।
এটি basic set intersection-এর মতো কাজ করে।
Checking Whether All Values Exist
Set<String> requiredRoles =
Set.of(
"INSTRUCTOR",
"COURSE_EDITOR"
);
Set<String> userRoles =
Set.of(
"INSTRUCTOR",
"COURSE_EDITOR",
"CONTENT_REVIEWER"
);
boolean hasRequiredRoles =
userRoles.containsAll(
requiredRoles
);
Result:
true
Iterating Over a Set
Enhanced for loop:
for (
String language
: supportedLanguages
) {
System.out.println(
language
);
}
Unlike List, index variable নেই।
Each element once process করা হয়।
HashSet Does Not Guarantee Iteration Order
Suppose:
Set<String> languages =
new HashSet<>();
languages.add(
"BN"
);
languages.add(
"EN"
);
languages.add(
"ET"
);
Printing may produce:
BN
EN
ET
or another order।
You must not assume:
Insertion order
Alphabetical order
Stable display order
HashSet-এর contract order guarantee করে না।
Do Not Depend on Current Printed Order
A small example may repeatedly print same order on one machine।
That does not make the order guaranteed।
Order can change due to:
- Different values
- Different Java versions
- Internal resizing
- Hash distribution
- Application changes
If output order matters, choose an ordered collection deliberately।
LinkedHashSet
LinkedHashSet uniqueness এবং insertion order দুটো preserve করে।
import java.util.LinkedHashSet;
Set<String> languages =
new LinkedHashSet<>();
languages.add(
"BN"
);
languages.add(
"EN"
);
languages.add(
"ET"
);
Iteration order:
BN
EN
ET
Use when:
- Unique values প্রয়োজন
- Insertion orderও meaningful
Variable type still:
Set<String>
Implementation:
new LinkedHashSet<>()
TreeSet: Brief Introduction
TreeSet unique values sorted order-এ রাখতে পারে।
import java.util.TreeSet;
Set<String> languages =
new TreeSet<>();
languages.add(
"ET"
);
languages.add(
"BN"
);
languages.add(
"EN"
);
Iteration:
BN
EN
ET
But element types must have a natural ordering or supplied comparator।
Detailed sorting এবং comparators later শেখানো হবে।
For now:
HashSet → No ordering guarantee
LinkedHashSet → Insertion order
TreeSet → Sorted order
Creating an Immutable Set with Set.of()
Set<String> supportedLanguages =
Set.of(
"BN",
"EN",
"ET"
);
This set:
- Cannot be structurally modified
- Does not allow null
- Does not allow duplicate arguments
- Does not guarantee a particular iteration order
Modifying Set.of()
supportedLanguages.add(
"FI"
);
Runtime-এ throws:
UnsupportedOperationException
Also:
supportedLanguages.remove(
"BN"
);
fails।
Duplicate Arguments in Set.of()
Set<String> values =
Set.of(
"JAVA",
"JAVA"
);
Runtime-এ throws:
IllegalArgumentException
Unlike HashSet.add(), which returns false for a duplicate, Set.of() rejects duplicate construction input।
Null in Set.of()
Set<String> values =
Set.of(
"JAVA",
null
);
Throws:
NullPointerException
Creating an Immutable Copy
Set<String> copy =
Set.copyOf(
supportedLanguages
);
The returned set cannot be structurally changed।
copy.add(
"FI"
);
throws:
UnsupportedOperationException
Set.copyOf() and Duplicates
If source is a collection with duplicates:
List<String> values =
List.of(
"JAVA",
"JAVA",
"SPRING"
);
Then:
Set<String> uniqueValues =
Set.copyOf(
values
);
Result contains unique elements:
JAVA
SPRING
Unlike Set.of("JAVA", "JAVA"), copying a general collection collapses duplicate elements according to set semantics।
Do not rely on its iteration order।
Mutable Copy of an Immutable Set
Set<String> mutableLanguages =
new HashSet<>(
Set.of(
"BN",
"EN"
)
);
Now:
mutableLanguages.add(
"ET"
);
works।
How HashSet Finds Elements
HashSet uses two important methods:
hashCode()
equals()
High-level process:
1. hashCode() helps find a possible storage location
2. equals() confirms whether an equal element already exists
Both methods must follow a valid contract।
The Equality Contract for Hash-Based Collections
Most important rule:
If two objects are equal according to
equals(), they must return the samehashCode().
Formally:
first.equals(
second
)
is true, then:
first.hashCode()
== second.hashCode()
must also be true।
The reverse is not required।
Two unequal objects may have the same hash code।
That situation is called a hash collision।
equals() then distinguishes them।
Strings Already Implement Equality Correctly
Set<String> values =
new HashSet<>();
String provides compatible:
equals()
hashCode()
So logically equal strings behave correctly in a set।
Java wrapper classes and many standard immutable types also implement these methods appropriately।
Custom Objects Without equals() and hashCode()
Consider:
public final class CourseCode {
private final String value;
public CourseCode(
String value
) {
this.value =
value.strip()
.toUpperCase();
}
}
Create two objects:
CourseCode first =
new CourseCode(
"java-oop"
);
CourseCode second =
new CourseCode(
"JAVA-OOP"
);
Logically they represent the same code।
But without overriding equality:
first.equals(
second
)
usually returns:
false
because default Object.equals() compares identity।
Duplicate Logical Values Can Enter the Set
Set<CourseCode> courseCodes =
new HashSet<>();
courseCodes.add(
first
);
courseCodes.add(
second
);
Without custom equality, size may be:
2
Even though both represent:
JAVA-OOP
Set only enforces uniqueness according to the element’s equality contract।
Implementing equals() and hashCode()
import java.util.Objects;
public final class CourseCode {
private final String value;
public CourseCode(
String value
) {
if (
value == null
|| value.isBlank()
) {
throw new IllegalArgumentException(
"Course code is required."
);
}
this.value =
value.strip()
.toUpperCase();
}
public String getValue() {
return value;
}
@Override
public boolean equals(
Object other
) {
if (this == other) {
return true;
}
if (
!(other
instanceof CourseCode courseCode)
) {
return false;
}
return value.equals(
courseCode.value
);
}
@Override
public int hashCode() {
return Objects.hash(
value
);
}
@Override
public String toString() {
return value;
}
}
Now:
CourseCode first =
new CourseCode(
"java-oop"
);
CourseCode second =
new CourseCode(
"JAVA-OOP"
);
first.equals(
second
);
returns:
true
And both have compatible hash codes।
Set Now Rejects the Logical Duplicate
Set<CourseCode> courseCodes =
new HashSet<>();
System.out.println(
courseCodes.add(
first
)
);
System.out.println(
courseCodes.add(
second
)
);
System.out.println(
courseCodes.size()
);
Output:
true
false
1
This is value-based uniqueness।
Why hashCode() Must Match equals()
Bad class:
@Override
public boolean equals(
Object other
) {
// Compares course code value
}
@Override
public int hashCode() {
return super.hashCode();
}
Two logically equal objects may get different identity-based hash codes।
HashSet may look in different locations and fail to detect the duplicate।
Result:
Logically equal values coexist unexpectedly
contains() may fail
remove() may fail
Always override both together when equality is value-based।
Do Not Use Random Values in hashCode()
Wrong:
@Override
public int hashCode() {
return (int) (
Math.random()
* 1_000
);
}
Hash code must remain consistent while equality-relevant state remains unchanged।
Same object changing hash code across calls breaks hash-based collections।
Mutable Elements Are Dangerous in HashSet
Consider a mutable class:
public final class MutableCourseCode {
private String value;
public void changeValue(
String value
) {
this.value = value;
}
@Override
public boolean equals(
Object other
) {
// Compares value
}
@Override
public int hashCode() {
return Objects.hash(
value
);
}
}
Add:
MutableCourseCode code =
new MutableCourseCode(
"JAVA"
);
Set<MutableCourseCode> codes =
new HashSet<>();
codes.add(
code
);
Then mutate equality-relevant state:
code.changeValue(
"SPRING"
);
Object was stored using old hash:
JAVA hash
Now it produces:
SPRING hash
Lookup Can Fail After Mutation
codes.contains(
code
);
may unexpectedly return:
false
And:
codes.remove(
code
);
may fail।
The object still physically exists inside the set, but its equality/hash identity changed after insertion।
Prefer Immutable Set Elements
Strong design:
public final class CourseCode {
private final String value;
}
No setter।
Equality-relevant state cannot change।
Useful immutable set elements include:
CourseCode
EnrollmentKey
UserRole
LanguageCode
LessonId
If an object must be mutable, avoid changing fields used by equals() and hashCode() while it belongs to a hash-based collection।
Entity Equality Requires Care
Suppose Course equality uses:
ID
and ID is stable।
Then mutable title may not affect hash-based membership।
But if equality uses mutable title:
title
renaming the course can break set lookup।
Practical guideline:
Hash-based equality should rely on stable identity or immutable value state.
Equality design is a domain decision, not only a technical method-generation task।
Set Equality
Two sets are generally equal when they contain the same elements, regardless of iteration order।
Set<String> first =
Set.of(
"BN",
"EN"
);
Set<String> second =
Set.of(
"EN",
"BN"
);
first.equals(
second
);
returns:
true
This differs from List equality, where order matters।
List Equality vs Set Equality
Lists:
List.of(
"BN",
"EN"
).equals(
List.of(
"EN",
"BN"
)
);
returns:
false
Sets:
Set.of(
"BN",
"EN"
).equals(
Set.of(
"EN",
"BN"
)
);
returns:
true
Because list models sequence।
Set models membership।
Null in HashSet
HashSet permits one null element।
Set<String> values =
new HashSet<>();
values.add(
null
);
values.add(
null
);
Size:
1
But allowing null often complicates processing।
for (
String value
: values
) {
value.toUpperCase();
}
can throw:
NullPointerException
Unless null has deliberate domain meaning, reject it।
Uniqueness Is Not Complete Business Protection
A Set prevents duplicates within one in-memory collection instance।
It does not automatically protect against:
- Two application servers inserting concurrently
- Database duplicate rows
- Multiple processes
- Restarted application state
- Race conditions
- Distributed requests
Production uniqueness may also require:
Database unique constraint
Transactional check
Idempotency
Concurrency control
Set is an in-memory data structure, not a complete distributed consistency mechanism।
Performance Mental Model
HashSet is designed for fast:
add
contains
remove
Average lookup is commonly described as near constant time।
But actual behavior depends on:
- Good
hashCode() - Number of collisions
- Collection size
- Runtime implementation
- Element equality cost
Do not choose a set only from Big-O memorization।
Choose it first because uniqueness and membership match the domain requirement।
Complete Example: Unique Enrollment Registry
একজন learner একই course-এ শুধু একবার enrolled হতে পারবে।
Uniqueness key:
learnerId + courseId
We will model it with an immutable value object।
EnrollmentKey.java
import java.util.Objects;
public final class EnrollmentKey {
private final long learnerId;
private final long courseId;
public EnrollmentKey(
long learnerId,
long courseId
) {
if (learnerId <= 0) {
throw new IllegalArgumentException(
"Learner ID must be positive."
);
}
if (courseId <= 0) {
throw new IllegalArgumentException(
"Course ID must be positive."
);
}
this.learnerId = learnerId;
this.courseId = courseId;
}
public long getLearnerId() {
return learnerId;
}
public long getCourseId() {
return courseId;
}
@Override
public boolean equals(
Object other
) {
if (this == other) {
return true;
}
if (
!(other
instanceof EnrollmentKey key)
) {
return false;
}
return learnerId
== key.learnerId
&& courseId
== key.courseId;
}
@Override
public int hashCode() {
return Objects.hash(
learnerId,
courseId
);
}
@Override
public String toString() {
return "EnrollmentKey{"
+ "learnerId="
+ learnerId
+ ", courseId="
+ courseId
+ '}';
}
}
EnrollmentRegistry.java
import java.util.HashSet;
import java.util.Set;
public final class EnrollmentRegistry {
private final Set<EnrollmentKey> enrollments;
public EnrollmentRegistry() {
this.enrollments =
new HashSet<>();
}
public boolean enroll(
long learnerId,
long courseId
) {
EnrollmentKey key =
new EnrollmentKey(
learnerId,
courseId
);
return enrollments.add(
key
);
}
public boolean isEnrolled(
long learnerId,
long courseId
) {
EnrollmentKey key =
new EnrollmentKey(
learnerId,
courseId
);
return enrollments.contains(
key
);
}
public boolean cancelEnrollment(
long learnerId,
long courseId
) {
EnrollmentKey key =
new EnrollmentKey(
learnerId,
courseId
);
return enrollments.remove(
key
);
}
public int getEnrollmentCount() {
return enrollments.size();
}
public Set<EnrollmentKey> getEnrollments() {
return Set.copyOf(
enrollments
);
}
}
Main.java
public class Main {
public static void main(
String[] args
) {
EnrollmentRegistry registry =
new EnrollmentRegistry();
boolean firstEnrollment =
registry.enroll(
101L,
501L
);
boolean duplicateEnrollment =
registry.enroll(
101L,
501L
);
boolean anotherCourse =
registry.enroll(
101L,
502L
);
boolean anotherLearner =
registry.enroll(
102L,
501L
);
System.out.println(
"First enrollment: "
+ firstEnrollment
);
System.out.println(
"Duplicate enrollment: "
+ duplicateEnrollment
);
System.out.println(
"Another course: "
+ anotherCourse
);
System.out.println(
"Another learner: "
+ anotherLearner
);
System.out.println(
"Enrollment count: "
+ registry
.getEnrollmentCount()
);
System.out.println(
"Learner 101 enrolled in course 501: "
+ registry.isEnrolled(
101L,
501L
)
);
boolean cancelled =
registry.cancelEnrollment(
101L,
501L
);
System.out.println(
"Cancelled: "
+ cancelled
);
System.out.println(
"Enrollment count after cancellation: "
+ registry
.getEnrollmentCount()
);
}
}
Possible output:
First enrollment: true
Duplicate enrollment: false
Another course: true
Another learner: true
Enrollment count: 3
Learner 101 enrolled in course 501: true
Cancelled: true
Enrollment count after cancellation: 2
Why Duplicate Enrollment Was Rejected
First call creates:
new EnrollmentKey(
101L,
501L
)
Second call creates another object with same values।
They are different object references।
But:
equals()
returns true because learner ID and course ID match।
And:
hashCode()
is compatible।
Therefore HashSet.add() returns:
false
for the second object।
Why EnrollmentKey Is Immutable
Fields:
private final long learnerId;
private final long courseId;
No setters।
Once added to HashSet, equality-relevant state cannot change।
This protects lookup behavior।
Why the Getter Returns Set.copyOf()
Weak:
public Set<EnrollmentKey> getEnrollments() {
return enrollments;
}
Caller could:
registry.getEnrollments()
.clear();
and bypass registry rules।
Safer:
return Set.copyOf(
enrollments
);
Caller gets an immutable structural copy।
When to Use Set
Use Set when:
- Duplicate values are invalid or meaningless
- Membership check is important
- Index access is unnecessary
- Order is irrelevant or separately specified
- Elements have stable equality semantics
Examples:
User roles
Course codes
Completed lesson IDs
Unique tags
Enrollment keys
Supported currencies
Feature permissions
When Set May Not Be Best
If requirements need:
Sequence
Position
Duplicate occurrences
use List।
If requirements need:
Lookup from key to associated value
use Map।
If requirements need:
Unique values in insertion order
consider LinkedHashSet।
If requirements need:
Unique sorted values
consider TreeSet।
List vs Set
| Requirement | List | Set |
|---|---|---|
| Preserves sequence | Yes | Depends on implementation |
| Index access | Yes | No |
| Allows duplicates | Yes | No |
| Membership-focused | Possible | Natural |
| Equality matters | Yes | Yes |
| Unique elements | Manual rule | Built-in contract |
| Multiple equal occurrences | Supported | Not supported |
Domain Choice Example
Course Lesson Sequence
List<Lesson>
Because:
- Order matters
- Same lesson position matters
- Index may be useful
User Roles
Set<Role>
Because:
- Duplicate
INSTRUCTORrole has no meaning - Membership check matters
- Position usually irrelevant
Learner Activity History
List<Activity>
Because:
- Repeated activities valid
- Chronological sequence matters
Completed Lesson IDs
Set<Long>
Because:
- A lesson is either completed or not
- Duplicate completion ID adds no meaning
Common Mistakes
Expecting Index Access
set.get(
0
);
Set has no index contract।
Depending on HashSet Iteration Order
Current output order is not guaranteed।
Forgetting to Check add() Result
The return value can directly indicate duplicate insertion।
Overriding equals() Without hashCode()
Hash-based lookup and duplicate detection become unreliable।
Using Mutable Equality Fields
Changing a field used by hashCode() after insertion may make the element unreachable।
Assuming Set Understands Domain Normalization
JAVA
java
remain distinct unless normalized or equality handles case-insensitivity।
Returning an Internal Mutable Set
Caller can bypass domain operations।
Using Set.of() and Then Mutating It
It throws UnsupportedOperationException।
Passing Duplicate Values to Set.of()
It throws IllegalArgumentException।
Assuming Set Solves Database Uniqueness
It only controls one in-memory collection।
Using Set When Order Is Business-Critical
Choose List, LinkedHashSet, or another explicit ordered model।
Practice Exercises
Exercise 1: Unique Course Codes
Create:
Set<String> courseCodes
Requirements:
- Normalize with
strip()andtoUpperCase() - Reject blank input
- Return
falsefor duplicates - Print final count
Exercise 2: User Roles
Create:
Set<String> roles
Add:
LEARNER
INSTRUCTOR
LEARNER
CONTENT_EDITOR
Predict and verify size।
Exercise 3: Immutable Supported Currencies
Create an immutable set:
BDT
EUR
USD
Verify add operation fails।
Exercise 4: Implement CourseCode
Create an immutable value object with:
value
equals()
hashCode()
toString()
Verify:
new CourseCode(
"java"
)
and:
new CourseCode(
"JAVA"
)
behave as one set element।
Exercise 5: Explain Mutation Risk
Create a mutable object whose name field is used by:
equals()
hashCode()
Add it to HashSet, change the name, then test:
contains()
remove()
Explain the unexpected behavior।
Exercise 6: Choose the Collection
Choose List, HashSet, or LinkedHashSet:
- Course lesson order
- Unique user permissions
- Unique tags displayed in insertion order
- Learner activity history
- Completed content IDs
- Playlist where duplicate songs are allowed
Explain each choice।
Exercise 7: Extend the Enrollment Registry
Add:
public Set<Long> findCourseIdsByLearnerId(
long learnerId
)
Requirements:
- Return unique course IDs
- Do not expose mutable internal state
- Return empty set when none found
Predict the Result
Question 1
Set<String> values =
new HashSet<>();
System.out.println(
values.add(
"JAVA"
)
);
System.out.println(
values.add(
"JAVA"
)
);
System.out.println(
values.size()
);
Question 2
Set<String> values =
Set.of(
"JAVA",
"JAVA"
);
What happens?
Question 3
Set<String> values =
Set.of(
"BN",
"EN"
);
values.remove(
"BN"
);
What happens?
Question 4
Set<String> first =
Set.of(
"BN",
"EN"
);
Set<String> second =
Set.of(
"EN",
"BN"
);
System.out.println(
first.equals(
second
)
);
Question 5
Two custom objects have equal field values but do not override equals() or hashCode()।
Can both enter a HashSet?
Question 6
An object’s hash-relevant field changes after insertion into a HashSet।
Can contains() unexpectedly fail?
Predict the Result Answers
Answer 1
true
false
1
Answer 2
Runtime-এ:
IllegalArgumentException
Duplicate arguments are not allowed।
Answer 3
Runtime-এ:
UnsupportedOperationException
Set.of() immutable।
Answer 4
true
Set equality element membership compare করে, order নয়।
Answer 5
হ্যাঁ।
Default equality normally compares object identity।
Answer 6
হ্যাঁ।
Object may now hash to a different location than where it was stored।
Knowledge Check
Question 1
Set-এর primary characteristic কী?
Question 2
HashSet.add() কী return করে?
Question 3
Set কি index-based?
Question 4
HashSet insertion order guarantee করে কি?
Question 5
Which set implementation preserves insertion order?
Question 6
Set.of() mutable কি?
Question 7
Set.of() duplicate arguments accept করে কি?
Question 8
HashSet duplicate detection-এ কোন methods গুরুত্বপূর্ণ?
Question 9
Equal objects-এর hash code সম্পর্কে rule কী?
Question 10
Same hash code কি objects equal হওয়া guarantee করে?
Question 11
Custom value object-এর জন্য শুধু equals() override করা যথেষ্ট কি?
Question 12
Mutable equality state hash set-এর জন্য risky কেন?
Question 13
Set equality-তে order matter করে কি?
Question 14
List এবং Set-এর central difference কী?
Question 15
Set কি database-level uniqueness guarantee করে?
Knowledge Check Answers
Answer 1
Duplicate elements রাখে না।
Answer 2
Set changed হলে true, equal element already থাকলে false।
Answer 3
না।
Answer 4
না।
Answer 5
LinkedHashSet।
Answer 6
না।
Answer 7
না। Duplicate থাকলে IllegalArgumentException হয়।
Answer 8
hashCode() এবং equals()।
Answer 9
Objects equal হলে তাদের hash codes same হতে হবে।
Answer 10
না।
Unequal objects একই hash code রাখতে পারে।
Answer 11
না।
Compatible hashCode()-ও override করতে হবে।
Answer 12
Mutation-এর পরে object অন্য hash location produce করতে পারে, ফলে lookup/remove fail করতে পারে।
Answer 13
না।
Same members থাকলে sets equal হতে পারে।
Answer 14
List sequence এবং duplicates model করে। Set unique membership model করে।
Answer 15
না।
Database constraints এবং concurrency protection separately প্রয়োজন হতে পারে।
Lesson Summary
এই lesson-এ আমরা শিখেছি:
Setunique elements store করেSetএকটি generic interfaceHashSetcommon mutable implementationadd()duplicate insertion detect করতে boolean return করে- Duplicate insertion set size increase করে না
- Set index-based নয়
contains()membership check করেremove()element value remove করেaddAll(),removeAll(),retainAll(), এবংcontainsAll()set operations support করে- Enhanced
forদিয়ে set iterate করা যায় HashSetorder guarantee করে নাLinkedHashSetinsertion order preserve করেTreeSetsorted uniqueness provide করতে পারেSet.of()immutable set তৈরি করেSet.of()duplicate এবং null reject করেSet.copyOf()immutable unique copy তৈরি করে- Set uniqueness element equality-এর ওপর depend করে
HashSethashCode()দিয়ে location narrow করে এবংequals()দিয়ে equality confirm করে- Equal objects must have equal hash codes
- Same hash code equal objects guarantee করে না
- Custom logical values-এর জন্য
equals()এবংhashCode()override করা প্রয়োজন - Hash-relevant mutable state collection behavior break করতে পারে
- Immutable value objects strong set elements
- Set equality order-independent
- List equality order-sensitive
- Null elements deliberate policy ছাড়া avoid করা ভালো
- Set in-memory uniqueness দেয়, distributed বা database uniqueness নয়
Listsequence model করেSetunique membership model করে- Collection choice domain meaning এবং required operations থেকে আসা উচিত
Next Lesson
পরবর্তী lesson:
Working with Map
আমরা শিখব:
- Key-value relationships
HashMap- Unique keys
put(),get(), এবংremove()- Replacing existing values
containsKey()এবংcontainsValue()- Missing keys এবং
null getOrDefault()- Iterating keys, values, and entries
- Key equality and
hashCode() - Mutable key risks
- Course code দিয়ে course lookup
- Learner ID দিয়ে enrollment lookup