Java interop¶
Zazr collections do not implement java.util.List, Set or Map, because they cannot support add() or put().
To pass one to Java code, asJava() (asJavaMap() for a map) gives a read-only view, without copying.
Views¶
| Receiver | Method | Returns |
|---|---|---|
Vector, List, Queue, LazyList, NonEmptyVector |
asJava() |
java.util.List |
HashSet, NonEmptySet |
asJava() |
java.util.Set |
LinkedHashSet |
asJava() |
SequencedSet |
TreeSet, NonEmptySortedSet |
asJava() |
NavigableSet |
HashMap, NonEmptyMap |
asJavaMap() |
java.util.Map |
LinkedHashMap |
asJavaMap() |
SequencedMap |
TreeMap, NonEmptySortedMap |
asJavaMap() |
NavigableMap |
Every view is O(1) to create. Reads go through to the Zazr value, which never changes, so a view never goes stale.
Every method that would modify the view throws UnsupportedOperationException, even one that would change nothing,
such as clear() on an empty view. That includes pollFirst() on a NavigableSet view and setValue on a map
entry.
var names = Vector.of("Ada", "Grace");
var view = names.asJava(); // java.util.List<String>
var second = view.get(1);
var rejected = Try.run(() -> view.add("Linus")).getCause() instanceof UnsupportedOperationException;
// second is "Grace", rejected is true
A view is equal to any JDK collection with the same content: a list view to a java.util.List with the same
elements in the same order, a set view to any java.util.Set, a map view to any java.util.Map.
Sorted views¶
The views of TreeSet and TreeMap navigate the tree: ceiling, floor, first, get and size are
O(log n). subSet, headMap, descendingSet and the like are views too.
To keep a range as a TreeSet or a TreeMap, use rangeFrom, rangeUntil, rangeTo and rangeFromUntil, and
minAfter and maxBefore in place of ceiling and lower (ceilingEntry and lowerEntry on a map)
(sets, maps).
var scores = TreeSet.of(10, 20, 30, 40).asJava(); // java.util.NavigableSet<Integer>
var atLeast25 = scores.ceiling(25); // Integer
var top = scores.tailSet(20, true); // java.util.NavigableSet<Integer>
var ages = TreeMap.of("Ada", 36, "Grace", 85).asJavaMap(); // java.util.NavigableMap<String, Integer>
var grace = ages.get("Grace"); // Integer
// atLeast25 is 30, top is [20, 30, 40], grace is 85
Lazy LazyList¶
The view of a LazyList computes no element before a read needs it: get(i) computes the first i + 1, an iterator
one per step. size(), lastIndexOf and hashCode compute the whole LazyList, so avoid them on an infinite one.
Copies¶
When a JDK API needs a collection it can modify, copy the view with the JDK constructor you need:
new java.util.ArrayList<>(vector.asJava()), new java.util.HashMap<>(map.asJavaMap()).
var mutable = new java.util.ArrayList<>(Vector.of(1, 2).asJava()); // java.util.ArrayList<Integer>
mutable.add(3);
var jdkSet = new java.util.HashSet<>(HashSet.of("a", "b").asJava()); // java.util.HashSet<String>
// mutable is [1, 2, 3], jdkSet holds a and b
The way back, and streams¶
To come back from Java:
ofAlltakes anyIterableorjava.util.stream.Stream.collector()collects ajava.util.stream.Stream(Builders).ofAllof the view of a value of its own type returns that value, without copying:Vector.ofAll(vector.asJava())isvector, andTreeMap.ofAll(map.asJavaMap())ismapwhen the comparator is the same.
In the other direction, stream() on any Zazr collection returns a java.util.stream.Stream.
var fromJdk = Vector.ofAll(java.util.List.of(3, 1, 2)); // Vector<Integer>
var sum = fromJdk.stream().mapToInt(Integer::intValue).sum();
var fromOptional = Option.ofOptional(java.util.Optional.of(4)); // Option<Integer>
// Vector(3, 1, 2), 6, Some(4)
Option converts to and from java.util.Optional with toOptional() and Option.ofOptional; Try to and from
CompletableFuture with toCompletableFuture() and Try.fromCompletableFuture.
JSON¶
The optional dev.zazr:zazr-jackson artifact teaches Jackson 3 to read and write the Zazr collections, Option and
the tuples: see Jackson.