Skip to content

Implement java.util.List on sequence wrappers - #26

Merged
codeboost merged 3 commits into
masterfrom
java-list-wrappers
Sep 15, 2026
Merged

codeboost merged 3 commits into
masterfrom
java-list-wrappers

Conversation

@codeboost

Copy link
Copy Markdown
Owner

Summary

Stacked on #25. Read and write views over array lists and linked array lists now implement the full read-only java.util.List contract, replacing the previous java.util.Collection implementation that only provided toArray.

  • Full read-only List surface. size, isEmpty, get with IndexOutOfBoundsException for negative and past-the-end indices, contains, containsAll, indexOf, lastIndexOf, listIterator with and without a start index, subList, and both toArray overloads including the typed-array form. Every mutating method throws UnsupportedOperationException, including on sublists and list iterators.
  • Live, non-materializing. Shared methods delegate to a Collections.unmodifiableList over an AbstractList proxy in xitdb.util.collection that streams the wrapper's seq. A sublist taken from a write view inside a transaction reflects later assoc calls.
  • Symmetric equality with Java lists. java.util.ArrayList.equals requires the other operand to be a List, so it previously returned false against a stored sequence even though the reverse comparison was true. Both directions now agree, and hashCode matches, so views and Java lists find each other in a HashSet.

Test plan

  • clojure -M:test: 237 tests, 3,157 assertions, 0 failures
  • New test walks the read-only List contract on read and write views for both vector and list storage, including nil elements, typed and oversized toArray buffers, bidirectional listIterator, sublist bounds, live sublists across an in-transaction assoc, and every mutator throwing
  • New test checks equals, hashCode, and HashSet membership in both operand orders against java.util.ArrayList

🤖 Generated with Claude Code

@codeboost
codeboost added this pull request to stack #27 September 15, 2026 08:40
@codeboost
codeboost removed this pull request from stack #27 September 15, 2026 13:56
@codeboost
codeboost changed the base branch from dates-and-keyshashes-fixes to master September 15, 2026 13:58
Read and write array-list and linked-array-list views now implement the
full read-only java.util.List contract instead of only toArray: size,
get with bounds checks on both ends, indexOf, containsAll, listIterator,
subList, and typed toArray. Mutating methods throw
UnsupportedOperationException. Sublists and iterators are live: a
sublist taken inside a transaction reflects later assocs.

Shared methods delegate to a Collections.unmodifiableList over an
AbstractList proxy that streams the wrapper's seq, so no
materialization happens. Since the wrappers are now List instances,
java.util.ArrayList.equals accepts them and equality is symmetric with
Java lists, including HashSet membership.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
codeboost and others added 2 commits September 15, 2026 16:20
Routing the transaction wrappers' iterator through listIterator made every
element read go through putCursor, a write path that copies index nodes.
Since coll-reduce dispatches on Iterable for these types, reduce, into and
mapv inside swap! duplicated the whole list in the append-only file on
every transaction (48 KB per 5000-element vector, 115 KB per list).

Iterate the seq again, which walks cursors without copying. The plain
iterator is therefore not live after assoc; listIterator and subList
iterators still are, and the test now asserts liveness only for those.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codeboost
codeboost merged commit fb5b45c into master Sep 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant