Lesson Completion
Back to course

Modern API Enhancements: Java 9-21 Improvements

Beginner
12 minutes4.6Java

1. The Hook (The "Byte-Sized" Intro)

  • In a Nutshell: Modern Java APIs (Java 9-21) add convenience methods.
  • Collection factories (Java 9): List.of(), Set.of(), Map.of() create immutable collections (no nulls).
  • Stream enhancements: takeWhile/dropWhile() (Java 9), toList() (Java 16).
  • String methods: isBlank(), lines(), strip(), repeat() (Java 11).
  • Optional improvements: ifPresentOrElse(), or(), isEmpty() (Java 9-11).
  • Benefits: Less boilerplate, functional style, immutability by default.
  • Key: Modern APIs favor immutability + fluent design!

Think of smartphone updates. Java 8 = basic phone. Modern Java = new shortcuts, widgets, gestures. Same phone, but smarter APIs (List.of() = quick contacts widget, isBlank() = smart text detection). Faster workflows!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Old APIs: Manual transmission car (more control, more work)
  • Modern APIs: Automatic car (convenience features, same destination)

3. Technical Mastery (The "Deep Dive")

Modern API Timeline

Java VersionKey APIs
Java 9Collection factories, Stream takeWhile/dropWhile, Optional improvements
Java 10Optional.orElseThrow()
Java 11String isBlank/lines/strip/repeat, Optional.isEmpty()
Java 16Stream.toList()
Java 21Sequenced collections

4. Interactive & Applied Code

java
import java.util.*; import java.util.stream.*; public class ModernAPIDemo { public static void main(String[] args) { demonstrateCollectionFactories(); demonstrateStreamEnhancements(); demonstrateStringMethods(); demonstrateOptionalImprovements(); } // Collection Factories (Java 9) static void demonstrateCollectionFactories() { System.out.println("=== COLLECTION FACTORIES ==="); // ❌ BEFORE: Verbose List<String> oldList = new ArrayList<>(); oldList.add("Alice"); oldList.add("Bob"); oldList = Collections.unmodifiableList(oldList); // ✅ AFTER: Concise, immutable List<String> list = List.of("Alice", "Bob", "Carol"); Set<String> set = Set.of("A", "B", "C"); Map<String, Integer> map = Map.of( "Alice", 30, "Bob", 25, "Carol", 28 ); System.out.println("List: " + list); System.out.println("Set: " + set); System.out.println("Map: " + map); // Immutable (throws UnsupportedOperationException) try { list.add("David"); } catch (UnsupportedOperationException e) { System.out.println("Cannot modify: " + e.getMessage()); } // No nulls allowed try { List.of("A", null, "C"); } catch (NullPointerException e) { System.out.println("No nulls: " + e.getMessage()); } // Map with many entries Map<String, Integer> bigMap = Map.ofEntries( Map.entry("key1", 1), Map.entry("key2", 2), Map.entry("key3", 3) ); } // Stream API Enhancements static void demonstrateStreamEnhancements() { System.out.println("\n=== STREAM ENHANCEMENTS ==="); // takeWhile() - take until condition false (Java 9) List<Integer> numbers = List.of(1, 2, 3, 4, 1, 2); List<Integer> taken = numbers.stream() .takeWhile(n -> n < 4) .collect(Collectors.toList()); System.out.println("takeWhile(<4): " + taken); // [1, 2, 3] // dropWhile() - drop until condition false (Java 9) List<Integer> dropped = numbers.stream() .dropWhile(n -> n < 4) .collect(Collectors.toList()); System.out.println("dropWhile(<4): " + dropped); // [4, 1, 2] // toList() - direct to immutable list (Java 16) List<Integer> list = numbers.stream() .filter(n -> n % 2 == 0) .toList(); // ✅ Shorter than collect(Collectors.toList()) System.out.println("toList: " + list); // Stream.ofNullable() - handle nullable (Java 9) String value = null; long count = Stream.ofNullable(value).count(); System.out.println("ofNullable count: " + count); // 0 // iterate() with predicate (Java 9) List<Integer> limited = Stream.iterate(0, n -> n < 10, n -> n + 1) .toList(); System.out.println("iterate: " + limited); } // String Methods (Java 11+) static void demonstrateStringMethods() { System.out.println("\n=== STRING METHODS ==="); // isBlank() - checks if blank (whitespace-only or empty) System.out.println("' '.isBlank(): " + " ".isBlank()); // true System.out.println("'hi'.isBlank(): " + "hi".isBlank()); // false // lines() - split by line terminators String multiline = "Line 1\nLine 2\nLine 3"; multiline.lines().forEach(System.out::println); // strip() - remove leading/trailing whitespace (Unicode-aware) String padded = " hello "; System.out.println("strip: [" + padded.strip() + "]"); System.out.println("stripLeading: [" + padded.stripLeading() + "]"); System.out.println("stripTrailing: [" + padded.stripTrailing() + "]"); // repeat() - repeat string n times System.out.println("repeat: " + "Hi".repeat(3)); // HiHiHi // indent() - add/remove indentation (Java 12) String text = "Hello\nWorld"; System.out.println("indent(4):\n" + text.indent(4)); // transform() - apply function (Java 12) String result = "hello".transform(s -> s.toUpperCase() + "!"); System.out.println("transform: " + result); // formatted() - like String.format (Java 15) String formatted = "Name: %s, Age: %d".formatted("Alice", 30); System.out.println("formatted: " + formatted); } // Optional Enhancements static void demonstrateOptionalImprovements() { System.out.println("\n=== OPTIONAL ENHANCEMENTS ==="); // ifPresentOrElse() - consumer + runnable (Java 9) Optional<String> opt = Optional.of("Present"); opt.ifPresentOrElse( value -> System.out.println("Value: " + value), () -> System.out.println("Empty") ); // or() - lazy alternative Optional (Java 9) Optional<String> empty = Optional.empty(); Optional<String> result = empty.or(() -> Optional.of("Default")); System.out.println("or: " + result.get()); // isEmpty() - opposite of isPresent (Java 11) System.out.println("isEmpty: " + empty.isEmpty()); // orElseThrow() - no-arg version (Java 10) try { empty.orElseThrow(); } catch (NoSuchElementException e) { System.out.println("orElseThrow: " + e.getClass().getSimpleName()); } // stream() - convert to Stream (Java 9) long count = Optional.of("value").stream().count(); System.out.println("stream count: " + count); } }

5. The Comparison & Decision Layer

TaskOld APIModern API
Create listnew ArrayList<>() + addList.of(...)
Check blanktrim().isEmpty()isBlank()
Split linessplit("\\n")lines()
Collect listcollect(Collectors.toList())toList()

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "List.of() vs Arrays.asList()?" Answer:

  • List.of(): Truly immutable, no nulls, compact
  • Arrays.asList(): Fixed-size, allows nulls, backed by array
java
List<String> asList = Arrays.asList("A", "B", "C"); asList.set(0, "X"); // ✅ OK: mutable elements asList.add("D"); // ❌ ERROR: fixed size List<String> listOf = List.of("A", "B", "C"); listOf.set(0, "X"); // ❌ ERROR: immutable listOf.add("D"); // ❌ ERROR: immutable Arrays.asList("A", null); // ✅ OK List.of("A", null); // ❌ ERROR: no nulls

Pro-Tip: takeWhile vs filter:

java
List<Integer> numbers = List.of(1, 2, 3, 4, 1, 2); // filter: checks ALL elements numbers.stream() .filter(n -> n < 4) .toList(); // [1, 2, 3, 1, 2] // takeWhile: stops at first false numbers.stream() .takeWhile(n -> n < 4) .toList(); // [1, 2, 3] (stops at 4!)

Topics Covered

Java Fundamentals

Tags

#java#programming#beginner-friendly

Last Updated

2025-02-01