Files

47 lines
3.2 KiB
Markdown

# sequenced
Companion code for the ankurm.com post *"Sequenced Collections in Java 21+: getFirst, getLast and
reversed()."* Module in `java-core-examples`, the Java-core series.
## Versions this was built and tested against
| Component | Version | Notes |
|---|---|---|
| JDK | 25.0.4.1+1 (Temurin, LTS) | JEP 431 shipped in JDK 21 (GA September 2023) and is unchanged since. |
| JUnit Jupiter | 5.11.0 | |
| Maven | 3.9.11 | |
## Quickstart
```bash
export JAVA_HOME=/path/to/jdk-21-or-newer
mvn compile
java -cp target/classes com.ankurm.sequenced.AcrossCollectionsDemo
java -cp target/classes com.ankurm.sequenced.FindLastDemo
java -cp target/classes com.ankurm.sequenced.ReversedViewIsLiveDemo
```
`scripts/run-all.sh` regenerates every file in `output/`. `scripts/run.sh <ClassName>` runs one
demo ad hoc.
## What's in here
| File | What it shows |
|---|---|
| `src/main/java/.../AcrossCollectionsDemo.java` | `getFirst`/`getLast`/`addFirst`/`addLast`/`reversed()` run against `ArrayList`, `ArrayDeque`, `LinkedHashSet`, `LinkedHashMap` and `TreeMap` - the one shared contract across five previously-unrelated types. |
| `src/main/java/.../FindLastDemo.java` | The three pre-Java-21 ways people found "the last element" of a `Set` (two stream tricks and a throwaway copy) next to the one-line `getLast()` replacement, with a note on why the old ways cost more than they looked like they did. |
| `src/main/java/.../ReversedViewIsLiveDemo.java` | `reversed()` is a live view, not a copy - mutating either side is visible through the other, immediately. |
| `src/test/java/.../SequencedCollectionsTest.java` | Pins all of the above as assertions, 6/6 passing. |
| `output/00-javap-sequenced-interfaces.txt` | `javap` output for `SequencedCollection`, `SequencedMap`, `SequencedSet` straight from the compiled JDK - the primary-source check this repo's discipline requires before describing any interface's method list. |
| `output/01-04` | Captured runs of the three demos and the test suite. |
## Notes worth knowing before reading the post
- **`TreeMap`/`TreeSet` already had most of this.** `firstEntry()`/`lastEntry()`/`pollFirstEntry()`/`pollLastEntry()` existed on `NavigableMap` since Java 6; what JEP 431 adds for sorted collections is mostly `reversed()` as a named counterpart to `descendingMap()`/`descendingSet()`, plus the shared interface. The real new capability lands on `LinkedHashSet` and `LinkedHashMap`, which had an iteration order but no vocabulary for "first" or "last" before this.
- **`reversed()` is a view.** See `output/03` - mutating the original after taking `reversed()` is visible through the view and vice versa. This is the most common assumption bug the feature produces.
- **`LinkedHashSet.getLast()` is O(1) in practice**, not by interface contract - it resolves through `SequencedCollection`'s default method path to the reversed view's first element, and `LinkedHashSet`/`LinkedHashMap` already maintain a doubly-linked insertion-order list internally, so there's no O(n) walk. That is an implementation detail of the JDK's `LinkedHashMap`, not a guarantee `SequencedCollection` itself makes for arbitrary implementors.
## License
MIT - see the [repo-wide LICENSE](../LICENSE).