You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+81-65Lines changed: 81 additions & 65 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,22 +22,36 @@
22
22
23
23
## Summary
24
24
25
-
*Chainable* is intended to be a rich, `Iterable`-based alternative to Java's `Stream` and Google's *guava*, heavily relying on lambdas and command chaining, but focused on functional trees (tries), 2D maps, and other useful non-sequential data structures, in addition to sequences (chains). It is heavily inspired by the iterator pattern, functional programming, lazy evaluation and C#'s `Enumerable`. It is designed to enable writing powerful yet readable code quickly, succinctly, and performing sometimes faster than its non-lazy/non-functional equivalents.
26
-
25
+
*Chainables* is a set of fluent interface-style sub types of `Iterable` with a large selection of methods facilitating the use of the
26
+
functional programming, the iterator pattern and lazy evaluation, intended for achieving code that is more succinct, readable, simpler to implement
27
+
and sometimes faster than its non-lazy/non-functional equivalent.
28
+
29
+
It includes support for data structures such as:
30
+
-**tree** (or trie) - (`ChainableTree`) enabling a number of lazy operations on trees defined in a functional-programming manner (including infinite trees)
- and the `Chainable` interface itself, which is intended to be a rich, `Iterable`-based alternative to Java's `Stream` and Google's *guava*.
35
+
27
36
The implementation is lightweight, based on Java 8, self-contained, i.e. it has no external dependencies, so as not to contribute to any sub-dependency versioning challenges.
A simple starting **chain** can be created using one of the factory methods on `Chainable`, such as [`from()`](https://www.javadoc.io/static/com.github.chainables/chainable/0.5.2/com/github/chainables/chainable/Chainable.html#from-T...-) or [`empty()`](https://www.javadoc.io/static/com.github.chainables/chainable/0.5.2/com/github/chainables/chainable/Chainable.html#empty-java.lang.Class-).
@@ -88,22 +108,21 @@ A simple **tree** can be created using the [`withRoot()`](https://www.javadoc.io
88
108
<details><summary>Example...</summary>
89
109
90
110
```java
91
-
// Example tree of String values
92
-
ChainableTree<String> tree =ChainableTree.withRoot("root");
111
+
// Example tree of String values
112
+
ChainableTree<String> tree =ChainableTree.withRoot("root");
93
113
```
94
114
95
115
and then child sub-trees can be assigned to it either:
96
116
- as explicitly pre-defined trees or values:
97
117
98
118
```java
99
-
// Assign explicit child subtrees
100
-
tree.withChildren(
101
-
ChainableTree
102
-
.withRoot("1")
103
-
.withChildren("1.1", 1.2"),
104
-
ChainableTree
105
-
.withRoot("2")
106
-
.withChildren("2.1", "2.2"));
119
+
tree.withChildren(
120
+
ChainableTree
121
+
.withRoot("1")
122
+
.withChildValues("1.1", "1.2"),
123
+
ChainableTree
124
+
.withRoot("2")
125
+
.withChildValues("2.1", "2.2"));
107
126
```
108
127
109
128
- or dynamically, using functional programming by providing a child-extracting lambda -- see the [tree processing example](#tree-processing), or more in the [Tree Examples](#tree-examples) section.
@@ -124,13 +143,13 @@ Tightly integrated with `Chainable` chains, the functional programming-based tre
124
143
-**infinite trees**, or trees of infinite depth, can be easily defined in terms of children-generating lambdas. For example, the code below defines a lazily evaluated infinite tree made of all the possible permutations of the letters *a*, *b* and *c*, where each layer of the tree consists of nodes of increasingly longer strings:
125
144
126
145
```java
127
-
char[] alphabet = { 'a', 'b', 'c' }; // Define alphabet to take letters from
146
+
char[] alphabet = { 'a', 'b', 'c' }; // Define alphabet to take letters from
128
147
ChainableTree<String> permutations =ChainableTree
129
-
.withRoot("") // Blank string at the root
148
+
.withRoot("") // Blank string at the root
130
149
.withChildValueExtractor(p ->Chainable
131
-
.empty(String.class) // Start with an empty chain of strings
150
+
.empty(String.class) // Start with an empty chain of strings
132
151
.chainIndexed((s, i) -> p + alphabet[i.intValue()]) // Append each alphabet item to the parent
133
-
.first(alphabet.length)); // Limit the children chain to the size of the alphabet
152
+
.first(alphabet.length)); // Limit the children chain to the size of the alphabet
134
153
```
135
154
136
155
If you were to begin to traverse this infinite tree, its initial few layers would look like this:
@@ -194,6 +213,8 @@ so that a subsequent chain can apply its logic to their outputs in a quasi-paral
194
213
195
214
-**breadth-first / depth-first traversal** - You can achieve a tree-like traversal of a chain, where children of each item extracted by the child-extracting lambda are inserted immediately ahead [`depthFirst()`](https://www.javadoc.io/static/com.github.chainables/chainable/0.5.2/com/github/chainables/chainable/Chainable.html#depthFirst-java.util.function.Function-) or appended to the end of the chain [`breadthFirst()`](https://www.javadoc.io/static/com.github.chainables/chainable/0.5.2/com/github/chainables/chainable/Chainable.html#breadthFirst-java.util.function.Function-), thereby resulting in a pre-order/depth-first or breadth-first traversal respectively.
196
215
216
+
-**crossing** - Using the `cross()` method, you can cross two chains to create one chain that iterates through all the pairs of the members of the two input chains, in a lazily evaluated fashion.
217
+
197
218
-**disjunctive filtering** - Using the [`whereEither()`](https://www.javadoc.io/static/com.github.chainables/chainable/0.5.2/com/github/chainables/chainable/Chainable.html#whereEither-java.util.function.Predicate...-) method, you can specify one or more filter predicates at the same time, with disjunctive (logical-OR) semantics. This means you can define specific filtering predicates for specific purposes and then just supply them all as parameters, rather than having to create yet another predicate that's an *OR* of the others.
198
219
199
220
-**skipping** of the leading sub-chain of items under various scenarios, e.g.:
@@ -209,7 +230,7 @@ so that a subsequent chain can apply its logic to their outputs in a quasi-paral
209
230
- chainable **string joining/splitting** operations - You can get a chain of tokens or characters out of a string with `Chainable`'s [`split()`](https://www.javadoc.io/static/com.github.chainables/chainable/0.5.2/com/github/chainables/chainable/Chainables.html#split-java.lang.String-java.lang.String-boolean-) method, process it using various `Chainable` APIs and go back to a string using [`join()`](https://www.javadoc.io/static/com.github.chainables/chainable/0.5.2/com/github/chainables/chainable/Chainable.html#join-java.lang.String-).
210
231
</details>
211
232
212
-
#### Two-dimensionals Maps
233
+
#### Two-dimensional Maps
213
234
214
235
> :warning: To do
215
236
@@ -250,20 +271,19 @@ Functional and design differences with streams aside, a level of interoperabilit
250
271
In this example, an infinite tree is defined with a child extracting lambda that generates strings as permutations of letters from the specified alphabet (*a, b, c*) of increasingly greater length. Then, a "view" of the tree is defined, limiting its depth to 4 layers (including the empty root). Finally, it is transformed into a string listing of all the permutations:
251
272
252
273
```java
253
-
char[] alphabet = { 'a', 'b', 'c' }; // Define alphabet to take letters from
274
+
char[] alphabet = { 'a', 'b', 'c' }; // Define alphabet to take letters from
254
275
ChainableTree<String> permutations =ChainableTree
255
-
.withRoot("") // Blank string at the root
276
+
.withRoot("") // Blank string at the root
256
277
.withChildValueExtractor(p ->Chainable
257
-
.empty(String.class) // Start with empty chain of strings
278
+
.empty(String.class) // Start with an empty chain of strings
258
279
.chainIndexed((s, i) -> p + alphabet[i.intValue()]) // Append each alphabet item to the parent
259
-
.first(alphabet.length)); // Limit the children chain to the size of the alphabet
280
+
.first(alphabet.length)); // Limit the children chain to the size of the alphabet
260
281
261
-
// Prepare a listing of the permutations
262
-
String text = permutationsUptoLength3 = permutations
0 commit comments