1. The Hook (The "Byte-Sized" Intro)
- In a Nutshell: Performance optimization = measure first, optimize second. Premature optimization = root of evil (optimize without data).
- Collections: ArrayList (fast access) vs LinkedList (fast insert), HashMap vs TreeMap.
- Strings: Use StringBuilder in loops (not +).
- Objects: Reuse expensive objects (ConnectionPool, DateFormat).
- Profiling tools: JProfiler, VisualVM, JMH.
- Golden rule: Profile β identify hotspot β optimize β measure improvement. Readable code > clever code!
Think of driving. Profiling = GPS speed analysis (find slow sections). Premature optimization = buying race car for city streets (unnecessary). String concatenation = stopping car repeatedly vs cruise control. Object pooling = reuse rental car vs buy new each trip!
2. Conceptual Clarity (The "Simple" Tier)
π‘ The Analogy
- Profiling: Health checkup (find actual problems)
- Premature Optimization: Worry about wrinkles at age 10
- StringBuilder: Shopping list (add items efficiently)
- Object Pooling: Library books (borrow, return, reuse)
3. Technical Mastery (The "Deep Dive")
java
// ===========================================
// 1. PREMATURE OPTIMIZATION (DON'T DO THIS!)
// ===========================================
// β BAD: Optimizing without measuring
class DataProcessor {
// Complex object pool, caching, bit manipulation...
// But is this even a bottleneck?
}
// β
GOOD: Simple first, profile, then optimize
class DataProcessor {
void process(List<Data> data) {
for (Data d : data) {
transform(d);
}
}
}
// If slow, profile β identify bottleneck β optimize THAT part
// ===========================================
// 2. COLLECTION PERFORMANCE
// ===========================================
// ArrayList vs LinkedList
// β
ArrayList: Random access O(1), insert O(n)
List<String> arrayList = new ArrayList<>();
arrayList.get(1000); // Fast: O(1)
arrayList.add(5, "x"); // Slow: O(n) - shift elements
// β
LinkedList: Random access O(n), insert O(1)
List<String> linkedList = new LinkedList<>();
linkedList.get(1000); // Slow: O(n) - traverse
linkedList.add(5, "x"); // Fast: O(1) - adjust pointers
// Rule: Use ArrayList unless you need frequent inserts/deletes
// Initial capacity (avoid resizing)
// β BAD: Grows multiple times
List<String> list = new ArrayList<>(); // Capacity 10
for (int i = 0; i < 10000; i++) {
list.add("item"); // Resizes many times!
}
// β
GOOD: Pre-allocate
List<String> list = new ArrayList<>(10000); // Capacity 10000
for (int i = 0; i < 10000; i++) {
list.add("item"); // No resizing!
}
// HashMap vs TreeMap
// β
HashMap: O(1) operations, no order
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("key", 1); // O(1)
// β
TreeMap: O(log n) operations, sorted
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("key", 1); // O(log n)
// Rule: Use HashMap unless you need sorted keys
// ===========================================
// 3. STRING HANDLING
// ===========================================
// β BAD: String concatenation in loop
String result = "";
for (int i = 0; i < 10000; i++) {
result += "item"; // Creates 10000 String objects!
}
// O(nΒ²) - each + creates new String
// β
GOOD: StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append("item"); // Efficient: O(n)
}
String result = sb.toString();
// String.format vs concatenation
// β Slower (but more readable)
String msg = String.format("Hello, %s! You have %d messages", name, count);
// β
Faster (but less readable)
String msg = "Hello, " + name + "! You have " + count + " messages";
// Rule: Use StringBuilder for loops, + for simple concat
// ===========================================
// 4. OBJECT CREATION
// ===========================================
// Reuse expensive objects
// β BAD: Create every time
public String formatDate(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // Expensive!
return sdf.format(date);
}
// β
GOOD: Reuse (but careful - SimpleDateFormat not thread-safe!)
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd"); // Thread-safe!
public String formatDate(LocalDate date) {
return FORMATTER.format(date);
}
// Static factory methods (can cache)
// β
Integer caching (-128 to 127)
Integer a = Integer.valueOf(127);
Integer b = Integer.valueOf(127);
System.out.println(a == b); // true (cached!)
Integer c = Integer.valueOf(128);
Integer d = Integer.valueOf(128);
System.out.println(c == d); // false (not cached)
// ===========================================
// 5. LOOP OPTIMIZATION
// ===========================================
// β BAD: Recalculate in every iteration
for (int i = 0; i < list.size(); i++) { // size() called every iteration!
process(list.get(i));
}
// β
GOOD: Hoist invariant code
int size = list.size(); // Calculate once
for (int i = 0; i < size; i++) {
process(list.get(i));
}
// β
BETTER: Enhanced for-loop (simplest)
for (Item item : list) {
process(item);
}
// Stream API (may be slower for small collections)
// Sometimes slower due to overhead
list.stream().forEach(this::process);
// Benchmark before using streams for performance-critical code!
// ===========================================
// 6. PROFILING
// ===========================================
// Use JMH for microbenchmarks
@Benchmark
public void stringConcatenation() {
String result = "";
for (int i = 0; i < 100; i++) {
result += "item";
}
}
@Benchmark
public void stringBuilder() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append("item");
}
}
// Run: mvn clean install && java -jar target/benchmarks.jar5. The Comparison & Decision Layer
| Scenario | Choice | Reason |
|---|---|---|
| Random access | ArrayList | O(1) vs LinkedList O(n) |
| Frequent inserts | LinkedList | O(1) vs ArrayList O(n) |
| String in loop | StringBuilder | Avoid O(nΒ²) |
| Need sorted keys | TreeMap | HashMap unordered |
| Small collection | For-loop | Stream overhead |
6. The "Interview Corner" (The Edge)
The "Killer" Interview Question:
"Why is String concatenation in a loop slow?"
Answer: Strings are immutable! Each + creates a NEW String object!
java
String s = "";
for (int i = 0; i < 3; i++) {
s += "x"; // Creates: "", "x", "xx", "xxx"
}
// 3 iterations = 3 String objects created!
// For n iterations = n String objects = O(n) space, O(nΒ²) time!
// StringBuilder: mutates internal character array
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++) {
sb.append("x"); // Modifies same object
}
// 1 StringBuilder object = O(n) space, O(n) timePro-Tips:
- Profile before optimizing:
bash
# VisualVM (JDK tool)
jvisualvm
# Java Flight Recorder
java -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s MyApp
# Find hotspots β optimize those first!- JVM optimizations (JIT compiler):
java
// Small methods get inlined automatically
int add(int a, int b) {
return a + b; // JVM inlines this!
}
// Trust the JVMβit's smart!