Algorithms and Problem Solving with Java
Java's Built-In Sorting and Searching APIs
আপনি একটি free preview lesson দেখছেন।
Lesson Overview
আগের কয়েকটি lesson-এ আমরা manually implement করেছি:
Linear Search
Binary Search
Bubble Sort
Selection Sort
Insertion Sort
Merge Sort
Quick Sort
এই implementationগুলো algorithm বুঝতে সাহায্য করেছে।
কিন্তু normal production Java code-এ আমরা সাধারণত নিজের sorting algorithm লিখি না।
Instead, Java standard library ব্যবহার করি।
Examples:
Arrays.sort(...)
Arrays.binarySearch(...)
List.sort(...)
Collections.sort(...)
Collections.binarySearch(...)
Object sorting-এর জন্য আমরা ব্যবহার করি:
Comparable<T>
Comparator<T>
এই lesson-এ আমরা শিখব:
Arrays.sort()- Sorting primitive arrays
- Sorting object arrays
List.sort()Collections.sort()- Natural ordering
Comparable<T>Comparator<T>Comparator.comparing(...)- Primitive comparator helpers
- Reversed ordering
- Multiple-field sorting
thenComparing(...)Arrays.binarySearch()Collections.binarySearch()- Searching with custom comparators
- Why sorting and searching must use the same ordering rule
- When manual algorithms should be replaced with standard-library APIs
Why Use Standard Library Sorting?
Suppose we need to sort:
int[] scores = {
90,
70,
85,
60
};
We could write:
bubbleSort(
scores
);
But ordinary application code should normally use:
Arrays.sort(
scores
);
Why?
Because standard-library code is:
Well tested
Optimized
Familiar to Java developers
Maintained as part of the platform
Less error-prone than custom implementations
The purpose of manually learning sorting algorithms was:
Understand the mechanics.
The purpose of standard APIs is:
Solve normal application problems reliably.
Arrays.sort()
For arrays, Java provides:
java.util.Arrays
Import:
import java.util.Arrays;
Example:
int[] numbers = {
40,
10,
30,
20
};
Arrays.sort(
numbers
);
After sorting:
[10, 20, 30, 40]
Arrays.sort() Mutates the Array
This is important।
Arrays.sort(
numbers
);
sorts:
the original array
It does not create a new sorted copy।
Preserve the Original Array
If original order matters:
int[] sorted =
Arrays.copyOf(
numbers,
numbers.length
);
Arrays.sort(
sorted
);
Now:
numbers
remains unchanged।
And:
sorted
contains the sorted version।
Sorting Primitive Arrays
Arrays.sort() supports primitive arrays such as:
int[]
long[]
double[]
char[]
byte[]
short[]
float[]
Example:
long[] prices = {
5000,
1500,
3000
};
Arrays.sort(
prices
);
Result:
[1500, 3000, 5000]
Sorting String[]
Strings have a natural ordering।
Example:
String[] names = {
"Sumu",
"Sakib",
"Nur",
"Subu"
};
Arrays.sort(
names
);
Result follows String natural ordering।
Natural Ordering
Some Java types already know how to compare themselves naturally।
Examples:
Integer
Long
Double
String
LocalDate
Conceptually:
Integer
→ numeric order
String
→ lexicographical order
LocalDate
→ chronological order
For custom classes, natural ordering can be defined through:
Comparable<T>
List.sort()
Suppose:
List<Integer> scores =
new ArrayList<>(
List.of(
90,
60,
80,
70
)
);
Sort:
scores.sort(
null
);
Passing:
null
means:
Use natural ordering.
Result:
[60, 70, 80, 90]
Clearer Natural Ordering
Instead of:
scores.sort(
null
);
you can also write:
scores.sort(
Comparator.naturalOrder()
);
This can be more explicit।
Required import:
import java.util.Comparator;
Collections.sort()
Older/common API:
Collections.sort(
scores
);
Import:
import java.util.Collections;
This also sorts a mutable list using natural ordering।
List.sort() vs Collections.sort()
Both can sort mutable lists।
Modern application code often prefers:
list.sort(
comparator
);
because sorting is expressed directly on the list।
Example:
scores.sort(
Comparator.naturalOrder()
);
But:
Collections.sort(
scores
);
is still valid and commonly encountered।
Mutable List Requirement
This fails conceptually:
List<Integer> scores =
List.of(
30,
10,
20
);
scores.sort(
Comparator.naturalOrder()
);
Why?
Because:
List.of(...)
returns an unmodifiable list।
Sorting requires reordering elements।
Use:
List<Integer> scores =
new ArrayList<>(
List.of(
30,
10,
20
)
);
then:
scores.sort(
Comparator.naturalOrder()
);
Comparable<T>
Suppose we define:
record Course(
String code,
String title,
long priceInPaisa
) {
}
What is the "natural" order of Course?
Could be:
code
title
price
There is no universal answer।
If the domain has one clear default ordering, we may implement:
Comparable<Course>
Example with Comparable
record Course(
String code,
String title,
long priceInPaisa
) implements Comparable<Course> {
@Override
public int compareTo(
Course other
) {
return code.compareTo(
other.code
);
}
}
Now Course's natural order is:
course code
Using the Natural Order
List<Course> courses =
new ArrayList<>();
courses.add(
new Course(
"SYSTEM-DESIGN",
"System Design",
800_000
)
);
courses.add(
new Course(
"JAVA",
"Java Foundation",
300_000
)
);
courses.add(
new Course(
"BACKEND",
"Backend Development",
500_000
)
);
courses.sort(
Comparator.naturalOrder()
);
Ordering:
BACKEND
JAVA
SYSTEM-DESIGN
compareTo() Contract Intuition
A comparison method returns an integer।
Conceptually:
negative
→ this comes before other
zero
→ equal in ordering
positive
→ this comes after other
Example:
code.compareTo(
other.code
);
Do Not Return Arbitrary Boolean Logic
Incorrect:
return priceInPaisa
> other.priceInPaisa
? 1
: -1;
This fails when prices are equal because it never returns:
0
Better:
return Long.compare(
priceInPaisa,
other.priceInPaisa
);
Avoid Subtraction Comparators
Bad:
return first - second;
Why?
Because subtraction can overflow for large integer values।
Prefer:
Integer.compare(
first,
second
);
For long:
Long.compare(
first,
second
);
Should Every Domain Class Implement Comparable?
No।
Only define a natural order when there is a meaningful, stable default।
Suppose Course can commonly be sorted by:
title
price
code
lesson count
publication date
If none is clearly the natural identity of ordering, forcing one through Comparable may be misleading।
In such cases, prefer:
Comparator<Course>
Comparator<T>
Comparator<T> defines ordering externally।
Example:
Comparator<Course> byPrice =
Comparator.comparingLong(
Course::priceInPaisa
);
Then:
courses.sort(
byPrice
);
Why Comparator Is Powerful
It lets the same type have multiple sort orders।
Example:
By code
By title
By price
By price descending
By title then code
without modifying the class each time।
Sort by Title
Comparator<Course> byTitle =
Comparator.comparing(
Course::title
);
Then:
courses.sort(
byTitle
);
Method Reference
This:
Course::title
means conceptually:
Given a Course,
extract its title.
Equivalent lambda:
course -> course.title()
We'll study method references more deeply in Modern Java।
Comparator.comparing()
For object-valued properties:
Comparator.comparing(
Course::title
);
This works because String has natural ordering।
Primitive Comparator Helpers
For primitive-like properties, prefer specialized helpers:
Comparator.comparingInt(...)
Comparator.comparingLong(...)
Comparator.comparingDouble(...)
Example:
Comparator<Course> byPrice =
Comparator.comparingLong(
Course::priceInPaisa
);
This avoids unnecessary boxing in the comparison path।
Sorting by Price
Example:
List<Course> courses =
new ArrayList<>(
List.of(
new Course(
"JAVA",
"Java Foundation",
300_000
),
new Course(
"BACKEND",
"Backend Development",
500_000
),
new Course(
"ALGORITHMS",
"Algorithms",
400_000
)
)
);
courses.sort(
Comparator.comparingLong(
Course::priceInPaisa
)
);
Result by price:
JAVA 300000
ALGORITHMS 400000
BACKEND 500000
Descending Order
Use:
reversed()
Example:
Comparator<Course> byPriceDescending =
Comparator.comparingLong(
Course::priceInPaisa
).reversed();
Then:
courses.sort(
byPriceDescending
);
Result:
BACKEND
ALGORITHMS
JAVA
Natural Reverse Order
For naturally ordered values:
numbers.sort(
Comparator.reverseOrder()
);
Example:
List<Integer> numbers =
new ArrayList<>(
List.of(
10,
30,
20
)
);
numbers.sort(
Comparator.reverseOrder()
);
Result:
[30, 20, 10]
Sorting by Multiple Fields
Suppose:
record Learner(
String name,
int score
) {
}
Data:
Sakib 90
Subu 80
Sumu 90
Nur 80
We want:
score ascending
then name ascending
Use:
Comparator<Learner> comparator =
Comparator.comparingInt(
Learner::score
).thenComparing(
Learner::name
);
thenComparing()
The first comparator decides primary ordering।
If two values compare equally, the next comparator is used।
Example:
score first
name second
This is common in production systems।
Example
learners.sort(
Comparator.comparingInt(
Learner::score
).thenComparing(
Learner::name
)
);
Possible result:
Nur 80
Subu 80
Sakib 90
Sumu 90
Descending Primary, Ascending Secondary
Suppose we want:
score descending
name ascending
Use:
Comparator<Learner> byScoreDescendingThenName =
Comparator.comparingInt(
Learner::score
)
.reversed()
.thenComparing(
Learner::name
);
Be Careful with reversed()
This:
Comparator.comparingInt(
Learner::score
)
.thenComparing(
Learner::name
)
.reversed();
reverses the entire composed comparator।
That means both:
score
and
name
ordering are reversed।
If only the primary field should be descending, reverse it before chaining:
Comparator.comparingInt(
Learner::score
)
.reversed()
.thenComparing(
Learner::name
);
Comparator as a Named Rule
For reusable domain sorting:
static final Comparator<Course> BY_PRICE =
Comparator.comparingLong(
Course::priceInPaisa
);
Then:
courses.sort(
BY_PRICE
);
This can improve readability when the ordering has business meaning।
Comparator Naming Matters
Compare:
Comparator<Course> comparator
with:
Comparator<Course> byPriceThenCode
The second communicates intent much better।
Sorting Arrays of Objects
Arrays.sort() also supports object arrays।
Example:
Course[] courses = {
new Course(
"JAVA",
"Java Foundation",
300_000
),
new Course(
"BACKEND",
"Backend Development",
500_000
)
};
Sort by comparator:
Arrays.sort(
courses,
Comparator.comparingLong(
Course::priceInPaisa
)
);
Primitive Arrays Cannot Use Object Comparator Directly
For:
int[]
you use the primitive Arrays.sort() overload।
You cannot pass:
Comparator<Integer>
directly to an int[] sort।
If custom ordering such as descending is needed, one option is to use:
Integer[]
but that introduces object boxing overhead।
Often, for primitive arrays, sort ascending and traverse backwards if all you need is descending processing।
Example: Descending Primitive Traversal
int[] numbers = {
40,
10,
30,
20
};
Arrays.sort(
numbers
);
for (
int i = numbers.length - 1;
i >= 0;
i--
) {
System.out.println(
numbers[i]
);
}
Output:
40
30
20
10
No need to convert to Integer[] just for printing in reverse order।
Searching Again
After sorting, Java provides built-in Binary Search।
For arrays:
Arrays.binarySearch(...)
For lists:
Collections.binarySearch(...)
Arrays.binarySearch()
Example:
int[] numbers = {
10,
20,
30,
40,
50
};
int index =
Arrays.binarySearch(
numbers,
30
);
Result:
2
Search Requirement
The array must already be sorted according to the same ordering expected by the search।
This is non-negotiable।
Incorrect:
int[] numbers = {
40,
10,
30,
20
};
Arrays.binarySearch(
numbers,
30
);
Correct:
Arrays.sort(
numbers
);
int index =
Arrays.binarySearch(
numbers,
30
);
Checking Presence
Simple membership check:
boolean found =
Arrays.binarySearch(
numbers,
target
) >= 0;
Missing Value
If missing:
result < 0
Remember:
Do not assume the result is always -1.
The negative value encodes an insertion point।
Collections.binarySearch()
Example:
List<Integer> numbers =
new ArrayList<>(
List.of(
10,
20,
30,
40
)
);
int index =
Collections.binarySearch(
numbers,
30
);
Result:
2
Sorting Before Collections.binarySearch()
numbers.sort(
Comparator.naturalOrder()
);
int index =
Collections.binarySearch(
numbers,
target
);
Binary Search with Objects
Suppose:
record Course(
String code,
String title,
long priceInPaisa
) {
}
We sort by code:
Comparator<Course> byCode =
Comparator.comparing(
Course::code
);
Then:
courses.sort(
byCode
);
To search by that ordering, the search must use the same comparator।
Search Target Object
Collections.binarySearch() compares objects।
So we need a Course search key compatible with the comparator।
Example:
Course target =
new Course(
"JAVA",
"",
0
);
Then:
int index =
Collections.binarySearch(
courses,
target,
byCode
);
Because byCode only compares:
code
the other fields do not affect the search।
Complete Example
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Course> courses =
new ArrayList<>(
List.of(
new Course(
"SYSTEM-DESIGN",
"System Design",
800_000
),
new Course(
"JAVA",
"Java Foundation",
300_000
),
new Course(
"BACKEND",
"Backend Development",
500_000
)
)
);
Comparator<Course> byCode =
Comparator.comparing(
Course::code
);
courses.sort(
byCode
);
Course target =
new Course(
"JAVA",
"",
0
);
int index =
Collections.binarySearch(
courses,
target,
byCode
);
System.out.println(
index
);
}
record Course(
String code,
String title,
long priceInPaisa
) {
}
}
Sorting and Searching Must Agree
This is one of the most important rules in this lesson।
If you sort by:
price
then Binary Search must also compare by:
price
You cannot sort by:
title
and then Binary Search using:
price
The data is not ordered correctly for that search criterion।
Wrong Example
Comparator<Course> byTitle =
Comparator.comparing(
Course::title
);
Comparator<Course> byPrice =
Comparator.comparingLong(
Course::priceInPaisa
);
courses.sort(
byTitle
);
Collections.binarySearch(
courses,
target,
byPrice
);
This violates Binary Search's ordering requirement।
Correct Example
courses.sort(
byPrice
);
Collections.binarySearch(
courses,
target,
byPrice
);
Same ordering rule।
Comparable Search
If Course implements Comparable<Course> by code:
Collections.sort(
courses
);
then:
Collections.binarySearch(
courses,
target
);
can use that same natural ordering।
Comparator vs Comparable
A useful distinction:
Comparable<T>
Ordering belongs to the type itself।
Method:
compareTo(...)
Good when:
One clear natural ordering exists.
Comparator<T>
Ordering is defined externally।
Method:
compare(...)
usually created through utility methods or lambdas।
Good when:
Multiple meaningful orderings exist.
Practical Rule
For many domain models:
Prefer Comparator
unless a natural ordering is truly obvious.
Do not make a class Comparable just because sorting may happen someday।
Example: Course Ordering Choices
A Course may reasonably be sorted by:
Code
Title
Price
Lesson count
Popularity
Creation time
No single ordering may deserve to be called:
the natural Course order
Comparators are therefore often clearer।
Comparator Composition
Suppose we want:
price ascending
then title ascending
then code ascending
Use:
Comparator<Course> ordering =
Comparator.comparingLong(
Course::priceInPaisa
)
.thenComparing(
Course::title
)
.thenComparing(
Course::code
);
This is significantly clearer than writing long manual comparison logic।
Manual Comparator
You can also write:
Comparator<Course> byPrice =
new Comparator<>() {
@Override
public int compare(
Course first,
Course second
) {
return Long.compare(
first.priceInPaisa(),
second.priceInPaisa()
);
}
};
But modern Java usually uses lambdas or comparator factory methods।
Lambda Comparator
Equivalent:
Comparator<Course> byPrice =
(
first,
second
) -> Long.compare(
first.priceInPaisa(),
second.priceInPaisa()
);
Cleaner:
Comparator<Course> byPrice =
Comparator.comparingLong(
Course::priceInPaisa
);
Prefer the factory method when it expresses the intent clearly।
Null Values and Sorting
Null introduces additional complexity।
Example:
List<String> names =
new ArrayList<>();
names.add(
"Sakib"
);
names.add(
null
);
Natural comparison cannot simply call methods on null।
Comparator provides helpers:
Comparator.nullsFirst(...)
Comparator.nullsLast(...)
Example: Nulls Last
names.sort(
Comparator.nullsLast(
Comparator.naturalOrder()
)
);
Result conceptually:
Sakib
null
Prefer Stronger Domain Invariants
Even though null-aware comparators exist, do not use them as an excuse to allow meaningless null values everywhere।
If:
Course title must never be null
validate that rule when constructing the Course।
Then sorting becomes simpler।
Sorting Cost
Built-in sorting does not make complexity disappear।
For general comparison-based object sorting, think broadly:
O(n log n)
for typical scalable library sorting behavior।
The exact implementation varies by data type and JDK internals।
For this course, focus on:
Use standard APIs
Understand the general complexity
Do not depend on internal algorithm details
Arrays.sort() Implementation Details
Do not build application logic around assumptions such as:
Arrays.sort always uses algorithm X.
Different overloads and Java versions may use different implementation strategies।
Treat:
Arrays.sort(...)
as an API contract, not an invitation to depend on internal implementation details।
Searching Cost
Binary Search:
O(log n)
But remember that preparing the data may require sorting:
O(n log n)
If you sort only to perform one search, Linear Search might still be simpler and cheaper overall।
Repeated Searches
If data is:
sorted once
searched many times
Binary Search becomes much more attractive।
Example:
Sort:
O(n log n)
Then each search:
O(log n)
Or Use a Map
If the real requirement is:
Find Course by code
then repeatedly Binary Searching a list may not be the best design।
A map may express the requirement better:
Map<String, Course>
Then typical lookup:
coursesByCode.get(
code
);
is average:
O(1)
Use sorting when ordering matters।
Use maps when key-based lookup is the main access pattern।
Search API vs Data-Structure Design
Do not think:
"I know Binary Search,
therefore every lookup should use it."
Instead ask:
Do I need ordering?
Do I need positional access?
Do I need fast lookup by key?
Will data change frequently?
How many searches will happen?
Algorithm and data structure should be chosen together।
Common Mistake 1 — Manual Bubble Sort in Application Code
Avoid:
bubbleSort(
values
);
when:
Arrays.sort(
values
);
solves the normal requirement।
Manual algorithms belong mainly to learning and specialized cases।
Common Mistake 2 — Sorting an Unmodifiable List
This:
List<Integer> numbers =
List.of(
3,
1,
2
);
numbers.sort(
Comparator.naturalOrder()
);
will fail because the list is unmodifiable।
Create a mutable copy:
List<Integer> numbers =
new ArrayList<>(
List.of(
3,
1,
2
)
);
Common Mistake 3 — Forgetting Mutation
Both:
Arrays.sort(...)
and:
list.sort(...)
reorder the existing structure।
If original order matters, copy first।
Common Mistake 4 — Wrong Binary Search Ordering
Sorting by:
title
and searching with:
price comparator
is invalid।
Sorting comparator and searching comparator must agree।
Common Mistake 5 — Forcing Comparable
Do not define:
implements Comparable<Course>
unless the type has a meaningful natural ordering।
Use comparators for contextual ordering।
Common Mistake 6 — Subtraction Comparator
Avoid:
return first.score()
- second.score();
Prefer:
Integer.compare(
first.score(),
second.score()
);
or:
Comparator.comparingInt(
Learner::score
);
Common Mistake 7 — Misplacing reversed()
If only one field should be descending, reverse that comparator before thenComparing()।
Correct:
Comparator.comparingInt(
Learner::score
)
.reversed()
.thenComparing(
Learner::name
);
Common Mistake 8 — Expecting Binary Search to Return First Duplicate
Normal Binary Search gives a matching position, not necessarily:
first match
or:
last match
Use specialized boundary logic when that distinction matters।
Common Mistake 9 — Using Binary Search for Key Lookup by Habit
If you repeatedly need:
ID → object
a Map may be a much better abstraction।
Common Mistake 10 — Depending on JDK Sorting Internals
Your code should depend on:
API behavior
not assumptions about the exact internal algorithm Java currently uses।
Practical Example — Course Sorting
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Course> courses =
new ArrayList<>(
List.of(
new Course(
"JAVA",
"Java Foundation",
300_000
),
new Course(
"SYSTEM-DESIGN",
"System Design",
800_000
),
new Course(
"BACKEND",
"Backend Development",
500_000
),
new Course(
"ALGORITHMS",
"Algorithms",
500_000
)
)
);
Comparator<Course> byPriceThenTitle =
Comparator.comparingLong(
Course::priceInPaisa
).thenComparing(
Course::title
);
courses.sort(
byPriceThenTitle
);
for (
Course course
: courses
) {
System.out.println(
course.title()
+ " - "
+ course.priceInPaisa()
);
}
}
record Course(
String code,
String title,
long priceInPaisa
) {
}
}
Possible output:
Java Foundation - 300000
Algorithms - 500000
Backend Development - 500000
System Design - 800000
Among equal prices:
Algorithms
comes before:
Backend Development
because title is the secondary ordering field।
Practical Example — Ranking Learners
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Learner> learners =
new ArrayList<>(
List.of(
new Learner(
"Sakib",
91
),
new Learner(
"Subu",
95
),
new Learner(
"Sumu",
95
),
new Learner(
"Nur",
88
)
)
);
Comparator<Learner> ranking =
Comparator.comparingInt(
Learner::score
)
.reversed()
.thenComparing(
Learner::name
);
learners.sort(
ranking
);
for (
Learner learner
: learners
) {
System.out.println(
learner.name()
+ " - "
+ learner.score()
);
}
}
record Learner(
String name,
int score
) {
}
}
Result:
Subu - 95
Sumu - 95
Sakib - 91
Nur - 88
Practice 1 — Sort an int[]
Given:
int[] scores = {
90,
60,
80,
70
};
sort ascending।
Solution
Arrays.sort(
scores
);
Practice 2 — Preserve Original
Create a sorted copy without changing the original।
Solution
int[] sorted =
Arrays.copyOf(
scores,
scores.length
);
Arrays.sort(
sorted
);
Practice 3 — Sort a List Naturally
List<String> names =
new ArrayList<>(
List.of(
"Sumu",
"Sakib",
"Nur"
)
);
Solution
names.sort(
Comparator.naturalOrder()
);
Practice 4 — Reverse Order
Sort:
List<Integer>
descending।
Solution
numbers.sort(
Comparator.reverseOrder()
);
Practice 5 — Sort Objects by Price
Given:
record Course(
String title,
long price
) {
}
Solution
courses.sort(
Comparator.comparingLong(
Course::price
)
);
Practice 6 — Price Descending
Solution
courses.sort(
Comparator.comparingLong(
Course::price
).reversed()
);
Practice 7 — Price Then Title
Solution
courses.sort(
Comparator.comparingLong(
Course::price
).thenComparing(
Course::title
)
);
Practice 8 — Search Sorted Array
Given:
int[] numbers = {
10,
20,
30,
40
};
search for 30।
Solution
int index =
Arrays.binarySearch(
numbers,
30
);
Practice 9 — Search Result
What does:
index >= 0
mean after binarySearch()?
Answer
The target was found at a valid index।
Practice 10 — Sort/Search Consistency
If a Course list is sorted using:
Comparator.comparing(
Course::code
)
what comparator should Binary Search use?
Answer
The same code-based comparator, or another comparator defining exactly the same ordering।
Practice 11 — Comparable or Comparator?
You need to sort Course by:
price
title
popularity
in different screens।
Which abstraction is more appropriate?
Answer
Usually:
Comparator<Course>
because multiple contextual orderings are required।
Practice 12 — Key Lookup
You repeatedly need:
Course code → Course
and sorting is irrelevant।
Which structure is probably more appropriate?
Answer
Map<String, Course>
rather than repeatedly sorting and Binary Searching a list।
True or False
Arrays.sort()mutates the supplied array.List.sort()can reorder an unmodifiableList.of(...).Comparabledefines natural ordering.Comparatorcan define multiple external orderings.Comparator.comparingLong()is useful for alongproperty.reversed()can reverse comparator ordering.thenComparing()adds a secondary ordering.- Binary Search works correctly regardless of how data was sorted.
- Sorting and Binary Search must use compatible ordering.
Arrays.binarySearch()returns a negative result when missing.- A domain type must always implement
Comparable. - Standard sorting APIs should normally replace textbook sorting algorithms in application code.
Answers
1. True
2. False
3. True
4. True
5. True
6. True
7. True
8. False
9. True
10. True
11. False
12. True
Knowledge Check
Question 1
Why should standard-library sorting normally be preferred over custom Bubble Sort or Quick Sort?
Question 2
What does Arrays.sort() do to the original array?
Question 3
What is natural ordering?
Question 4
What does Comparable<T> represent?
Question 5
What does Comparator<T> represent?
Question 6
When is Comparator preferable to Comparable?
Question 7
What does Comparator.comparingLong() do?
Question 8
What does thenComparing() do?
Question 9
Why must sorting and Binary Search use the same ordering rule?
Question 10
Why should subtraction usually not be used to implement numeric comparison?
Question 11
Why can a Map be better than Binary Search for repeated key lookup?
Question 12
Why should application code avoid depending on the exact internal sorting algorithm used by the JDK?
Knowledge Check Answers
Answer 1
Because standard-library implementations are tested, optimized, maintained, familiar, and significantly less likely to contain subtle algorithmic bugs।
Answer 2
It sorts the supplied array in place, changing its element order।
Answer 3
Natural ordering is the default ordering defined by a type, such as numeric order for Integer or lexicographical order for String।
Answer 4
Comparable<T> allows a type to define its own natural ordering through:
compareTo(...)
Answer 5
Comparator<T> defines an ordering externally and allows the same type to have multiple different sorting rules।
Answer 6
When a type has several meaningful contextual orderings or no obvious single natural order।
Answer 7
It creates a comparator based on a long property extracted from an object।
Answer 8
It adds another comparison rule that is used when the earlier comparison considers two elements equal।
Answer 9
Binary Search decides which half to discard based on ordering. If its comparison rule differs from the rule used to sort the data, those decisions become invalid।
Answer 10
Subtraction can overflow and can therefore produce an incorrect comparison result for some numeric values।
Answer 11
A hash-based Map provides typical average O(1) lookup by key and directly models:
key → value
which may fit the requirement better than ordered searching।
Answer 12
Implementation details can differ between overloads and Java versions. Application code should depend on the public API's behavior rather than undocumented implementation choices।
Practical Decision Guide
Use:
Arrays.sort(...)
when:
You have an array
and need normal sorting.
Use:
list.sort(...)
when:
You have a mutable List
and need a specific ordering.
Use:
Comparable<T>
when:
The type has one genuinely natural order.
Use:
Comparator<T>
when:
Ordering depends on context
or multiple orders are useful.
Use:
Arrays.binarySearch(...)
when:
An array is already sorted
using compatible ordering.
Use:
Collections.binarySearch(...)
when:
A List is sorted
using compatible ordering.
Use:
HashSet
when:
Fast exact membership matters
and ordering is not required.
Use:
HashMap
when:
Fast key → value lookup
is the real requirement.
Lesson Summary
এই lesson-এ আমরা manual sorting/searching থেকে production-oriented Java APIs-এর দিকে এসেছি।
We learned:
Arrays.sort()sorts arrays in place- Primitive and object arrays can be sorted using standard APIs
List.sort()sorts mutable listsCollections.sort()is another standard list-sorting API- Natural ordering is the default ordering of comparable types
Comparable<T>defines a type's natural orderComparator<T>defines external/context-specific orderingComparator.comparing()sorts by object-valued propertiescomparingInt(),comparingLong(), andcomparingDouble()are useful for primitive propertiesreversed()reverses orderingthenComparing()supports multiple-field sorting- Comparator chaining can express business sorting rules clearly
Arrays.binarySearch()searches sorted arraysCollections.binarySearch()searches sorted lists- Binary Search must use the same ordering semantics as sorting
- Missing Binary Search results are negative
- Standard sorting APIs should normally replace textbook manual sorts
- A Set or Map may be more appropriate than Binary Search for some lookup requirements
- Application code should depend on API contracts rather than JDK implementation details
The core production principle is:
Learn algorithms manually
to understand how they work.
Use standard Java APIs
for ordinary application code.
And for object ordering:
Comparable
→ one natural order
Comparator
→ contextual and multiple orders
Next Lesson
পরবর্তী lesson:
Using Stacks, Queues, and Deques in Algorithms
আমরা শিখব:
- Choosing FIFO vs LIFO
- Stack-based algorithms
- Balanced brackets
- Undo-style processing
- Iterative traversal with Stack
- Queue-based algorithms
- Breadth-first processing intuition
- Deque-based problems
- Using
ArrayDequeas an algorithmic worklist - How data-structure choice changes algorithm behavior