ConsList
is an immutable singly-linked list:
ConsList.java.
This reliable and performant version of singly-linked
Cons List in Java implements the java.util.Collection
interface, giving
the programmers the access to all its methods such as stream()
,
toString()
and others.
This implementation of Cons List does not use recursion, so it will
not cause a StackOverflowError
. A list is allowed to contain more
than Integer.MAX_VALUE
elements and will produce an overhead of two
object references per element.
For further performance increase, primitive-type specializations can be used:
IntConsList
, LongConsList
, and DoubleConsList
, all of which extend
the parent ConsList
interface, while adding their own primitive-based methods
on top.
Collection methods are implemented:
size()
iterates through the list to avoid storing list lengthisEmpty()
does not try to calculate the size to see if it is 0.
Java 8 Streams support:
spliterator()
has the right characteristics for the cons list:ORDERED
andIMMUTABLE
.- a custom Collector
toConsCollector()
is provided.
Methods equals(Object o)
and hashCode()
are also implemented
without recursion.
Finally, the class is Serializable
. The serialization and de-serialization
operations are implemented using loops instead of recursion, thereby
safeguarding against a StackOverflowError
.
Cons List, due to its simplicity and immutability, is an ideal data structure for multi-threaded processing of ordered collections of data. Direct implementations however, suffer from heavy recsive calls and may cause high stack memory consumption, if not more severe issues. This implementation fuses the power of the immutable cons list with the wide range of functionality offered by the Java Collections and Streams API.
<dependency>
<groupId>io.github.nblxa</groupId>
<artifactId>cons-list</artifactId>
<version>2.1.0</version>
</dependency>
The library uses Semantic Versioning.
Static imports for ease of use:
import static io.github.nblxa.cons.ConsList.*;
Create an empty Cons list:
Collection<?> empty = nil();
Create a list of an arbitrary length:
Collection<String> strings = list("Hello", "functional", "programming", "!");
Adding new elements to a list is just creating new immutable lists:
Collection<String> strings2 = cons("ConsList", cons("says:", strings));
Note that since Cons List is immutable, it must be initialized with elements
at the time of creation. Another option is to initialize it with elements of
another Iterable
:
Collection<String> colors = consList(Arrays.asList("red", "black", "magenta"));
Create a primitive-based list of long
values:
LongConsList<Long> longs = longList(1L, 1L, 2L, 3L, 5L, 8L, 13L);
Create a list from a Stream
:
ConsList<String> fruit = Arrays.stream(new String[] {"Apples", "Bananas", "Oranges"})
.filter(f -> !f.startsWith("O"))
.collect(toConsCollector());
Being an immutable collection, ConsList
lets one save resources on defensive
copying where it would otherwise have been necessary for mutable collections,
such as ArrayList
.
Specific problems like flattening a tree-like hierarchical structure can be
solved more optimally with ConsList
, however the trivial list-growth and
iteration operations perform better using java.util.ArrayList
.
Specialized implementations for primitive types, like the IntConsList
,
for instance, may outperform ArrayList
in some benchmarks due
to the lack of boxing.
Here are the benchmark results on the author's machine:
Collection | Avg time, ms/op |
---|---|
io.github.nblxa.cons.ConsList |
29,659 |
java.util.ArrayList |
78,018 |
java.util.LinkedList |
112,173 |
Collection | Avg time, ms/op |
---|---|
io.github.nblxa.cons.IntConsList |
6,767 |
io.github.nblxa.cons.ConsList |
22,137 |
java.util.ArrayList |
9,507 |
java.util.LinkedList |
14,763 |
Note: The values for ConsList
and IntConsList
assume creating the list with
the reversed order of input values compared to those for ArrayList
and LinkedList
.
If the reversed order is not possible, a somewhat slower reverse()
or intReverse()
operation is required, adding one single list iteration and re-construction.
Collection | Avg time, ms/op |
---|---|
io.github.nblxa.cons.IntConsList |
3,058 |
io.github.nblxa.cons.ConsList |
4,845 |
java.util.ArrayList |
1,989 |
java.util.LinkedList |
10,451 |
The benchmark is written with JMH. To test the performance on your machine, build the project:
./mvnw clean package
and the benchmarks run:
java -jar cons-list-jmh/target/benchmarks.jar