Skip to content
academia.sh

Course Intermediate

The Standard Library and Streams

By the end of this course

Start course

01

Collections

The collections framework's interface hierarchy and implementations, the guarantees list, set, and queue choice rests on, where hash-based and sorted maps diverge, the iterator's response to a change during iteration, and the scope difference between natural order and a comparator.

  1. 01 Collections Framework The same three implementations are run side by side for four separate families, and seven of fifteen observations come out as interface guarantees, eight as the chosen class's implementation behavior alone. The bounding measurement bounds this very distinction: on a four-element source, PriorityQueue's iteration order matches its exit order by coincidence, and once a fifth element is added the distinction becomes visible again.
  2. 02 List, Set, and Queue The same six-element workload is given to a list, a set, and a queue implementation at once, and what each one drops from the input is counted: the list drops nothing, the set drops three pieces of information, the queue drops only positional access. The bounding measurement arises from LinkedList being both a list and a queue at the same time: both interfaces give a remove promise, the promises collide in a single call line, and the identically written remove(1) does two separate jobs — both guarantees hold, the gap is in the line the caller writes, and the break is silent.
  3. 03 Maps A key-value map's three promises — the key's uniqueness, the key view's liveness, a missing key giving null — come out the same across all three implementations and belong to the interface. Iteration order, null-key acceptance, and the requirement that a key be comparable, though, diverge between the hash-based and the sorted implementation. The caller's rule is put at the center for the first time: a lookup with a key that writes equals but not hashCode returns null with no exception at all, while the same key is found silently in a sorted map, because the promise used there is compareTo.
  4. 04 Iterators and Concurrent Modification The iterator's basic promise — NoSuchElementException once exhausted — comes out byte-for-byte identical across three separate implementations. But if the container changes during iteration, three separate answers appear: one that fails fast, one that walks over a snapshot, one that says nothing at all. Fail-fast itself turns out to be a best effort, not a guarantee: the same removal throws an exception at one position while leaving a loop that finishes silently, one short, at the second-to-last element. The bounding measurement shows the iterator's own remove falls outside this rule.
  5. 05 Comparison and Sorting Natural order sits in a type's own compareTo, the comparator in a separate object the caller gives from outside; the same data can be arranged in two separate orders. Stable sorting is List's own promise and comes out byte-for-byte identical across two separate list implementations. The caller's rule: a comparator inconsistent with equals collapses two separate elements into one in a sorted set, a non-transitive comparator silently sorts wrong on small input and falls by name on large enough input. The bounding measurement shows the same comparator loses no element in a list — what produces the flaw is not the comparator, it is the container that turns it into a uniqueness decision.

02

Functional Java

The promise single-abstract-method types carry as an interface, lambda expressions' capture rule, what the stream API's intermediate and terminal operations guarantee and what they do not, collectors' grouping and reducing behavior, expressing absence as a type.

  1. 01 Functional Interfaces Single abstract method is a compile-time promise: a two-method interface can never be a lambda target, and the marker only catches a definition that breaks this promise early. The interface's second promise — behavior — gets checked nowhere: the type promise gets compiled in all four members of the family, while the purity and no-side-effects promise can break silently in Predicate and Function.
  2. 02 Lambda Expressions When a lambda expression captures a local variable around it, that variable being effectively final is mandatory at compile time; when it captures a field, no such constraint exists, and the same lambda gives a different result once the object changes later. What gets frozen in a captured local variable is its value, not the object it points to.
  3. 03 Stream API Java's stream chain guarantees three of ten operations independent of the source, defers five to the source's order, and leaves two to the caller. An intermediate operation never runs without a terminal operation, but even once a terminal operation gets called, which item gets visited is not guaranteed. Consuming the same stream twice and growing the source while iterating both fall with an exception.
  4. 04 Collectors A collector gets built from four parts: supplier, accumulator, combiner, finisher. The result container's type and mutability are not the interface's promise — toList() returns a mutable list but promises this nowhere, while toUnmodifiableList() guarantees immutability. Once a duplicate key gets encountered, the map collector gives an exception, grouping merges.
  5. 05 `Optional` Expressing absence as a type does not move the caller's obligation to compile time: all four unchecked calls — both in the null-returning signature and the Optional-returning signature — compile unchecked, and one falls at runtime. The gain is visibility in the signature; this gain disappears in a field and a parameter, and of() falls immediately on null while ofNullable() does not.

03

Input/Output and Time

Where byte and character streams diverge and the decision encoding leaves to the caller, the promises the file system API gives in path and directory operations, object serialization bypassing the constructor mechanism, what date-time types carry and do not carry, and the behavior of pattern compilation and matching.

  1. 01 Stream-Based Input/Output It is measured that the byte stream promises nothing for write(int) beyond the low eight bits, that the character stream leans on an encoding, and that buffering changes only the call count reaching the stream below it, not the promise. The bounding measurement shows an unflushed buffer leaves data incomplete.
  2. 02 File System API That a path is a parsed value, and that normalization and resolution answer without ever touching the file system, is shown by running it on two separate providers. It is measured that directory traversal order is unspecified, and that existence-checking and opening are two separate operations.
  3. 03 Serialization Serialization is measured as never running the constructor, and as a consequence the invariants a constructor sets up can be skipped by a byte stream that arrived from outside. It shows how a readback hook brings the check back, and how a field name together with a version ID turns into a contract.
  4. 04 Date and Time API Measured by running whether each of three types (instant, local date-time, zoned date-time) can correctly answer the question 'does this show the same instant.' It shows that comparing without a time zone silently gives the wrong result, and that the gap and the overlap at a daylight saving transition are a place where the API picks a side by rule.
  5. 05 Regular Expressions Measures that a pattern is a compiled value, that exact matching and searching carry separate contracts, and that a greedy and a reluctant quantifier produce different captures on the same input. Shows that recompiling the pattern on every call is ineffective, and that backtracking's step count does not grow linearly with the input.

Start typing to search.

↑↓ Esc navigate · open · close