Collections¶
Every Zazr collection is immutable. An operation returns a new collection and shares what it can with the old one, which is never modified.
Each type declares its own methods, with its own return types, and every positional method documents its cost. The complexity page lists them all.
Which one to choose¶
| You need | Choose | Because |
|---|---|---|
| a sequence, by default | Vector |
effectively O(1) get, update, append, prepend, take, drop |
| a sequence that has at least one element | NonEmptyVector |
head, max, reduce cannot fail |
| to take a sequence apart head first, or a stack | List |
O(1) prepend, head, tail; switch on Cons and Nil |
| first in, first out | Queue |
amortised O(1) enqueue and dequeue |
| a sequence computed on demand, possibly infinite | Stream |
lazy and memoised |
| a set, by default | HashSet |
effectively O(1) contains, add, remove |
| a set in insertion order | LinkedHashSet |
a HashSet plus the insertion order, with positional methods |
| a sorted set | TreeSet |
O(log n) lookups and updates, positional methods in comparator order |
| a map, by default | HashMap |
effectively O(1) get, put, remove |
| a map in insertion order | LinkedHashMap |
a HashMap plus the insertion order, with positional methods |
| a sorted map | TreeMap |
O(log n) lookups and updates, positional methods in key order |
What they share¶
Every collection except NonEmptyVector implements Traversable<T>. It has what works the same way on every type: iterating, size,
contains, find, foldLeft, mkString, the conversions such as toVector and stream(), and the
asJava() view.
map, filter and the rest are declared by each type, so they return that type.
Two more operations exist on most types:
partitionMapsplits a collection in one pass, using a function that returns anEither. The sequences and the hash sets have it.- The static
flattenremoves one level of nesting.
Tuple2<List<Integer>, List<String>> split = List.of(1, 2, 3, 4)
.partitionMap(n -> n % 2 == 0 ? Either.left(n) : Either.right("odd " + n));
Vector<Integer> flat = Vector.flatten(Vector.of(Vector.of(1, 2), List.of(3)));
// split is (List(2, 4), List(odd 1, odd 3)), flat is Vector(1, 2, 3)
Vector<Integer> vector = Vector.of(3, 1, 2);
List<Integer> sortedList = vector.toList().sorted();
HashSet<Integer> set = HashSet.ofAll(vector);
boolean same = Vector.of(1, 2, 3).equals(sortedList);
// List(1, 2, 3), a HashSet of 1, 2, 3, and true
A Vector, List, Queue or Stream equals another of these four when they hold equal elements in the same
order. Sets equal sets and maps equal maps. A NonEmptyVector equals only another NonEmptyVector.
Nulls¶
No collection holds null: adding a null element, key or value throws a NullPointerException. Absence is an
Option, which is what find, headOption and Map.get return.
Option<Integer> missing = HashMap.of("a", 1).get("b");
Option<Integer> firstEven = Vector.of(1, 3, 4).find(n -> n % 2 == 0);
// None, Some(4)
Complexity¶
Each collection's page has a table of its common operations. Complexity puts all the collections side by side and lists every documented method.