Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/davidmoten/kool
j.u.s.Stream alternative (synchronous only), reusable, faster, more operators, easier to use.
https://github.com/davidmoten/kool
functional-programming java method-chaining stream synchronous
Last synced: about 1 month ago
JSON representation
j.u.s.Stream alternative (synchronous only), reusable, faster, more operators, easier to use.
- Host: GitHub
- URL: https://github.com/davidmoten/kool
- Owner: davidmoten
- License: apache-2.0
- Created: 2018-08-22T05:13:42.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2024-04-03T09:55:53.000Z (7 months ago)
- Last Synced: 2024-04-03T10:48:00.113Z (7 months ago)
- Topics: functional-programming, java, method-chaining, stream, synchronous
- Language: Java
- Homepage:
- Size: 990 KB
- Stars: 14
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# kool
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.davidmoten/kool/badge.svg?style=flat)](https://maven-badges.herokuapp.com/maven-central/com.github.davidmoten/kool)
[![codecov](https://codecov.io/gh/davidmoten/kool/branch/master/graph/badge.svg)](https://codecov.io/gh/davidmoten/kool)Alternative to `java.util.stream.Stream`:
* is sometimes much faster for synchonronous use ([benchmarks](benchmarks.md))
* has many [more operators](https://davidmoten.github.io/kool/apidocs/org/davidmoten/kool/Stream.html) and is generally **less verbose**
* operators are **more discoverable**
* streams are **reusable**
* **disposes** resources
* is designed for **synchronous use only**
* models **0..1** and **1** element streams explicitly with **`Maybe`** and **`Single`**.
* does not support streams of nulls (use `Optional` or `Maybe`)
* 30% **faster** on *Shakespeare Plays Scrabble* [benchmark](benchmarks.md)
* has **time-based** operators
* has statistics operator (reduction) that offers count, mean, sd, variance, kurtosis, skewness, min, max, rangeStatus: *available on Maven Central*
Maven site reports are [here](https://davidmoten.github.io/kool) including [javadoc](https://davidmoten.github.io/kool/apidocs/index.html).
If you need non-blocking and/or asynchronous streaming use [RxJava](https://github.com/ReactiveX/RxJava).
Note also that [IxJava](https://github.com/akarnokd/ixjava) predates this library and is also a pull-based and iterator-based library for reusable streams but does not model `Maybe` and `Single`.
## How to build
```bash
mvn clean install
```## Getting started
Add this dependency to your pom.xml:```xml
com.github.davidmoten
kool
VERSION_HERE```
## Example
```java
import org.davidmoten.kool.Stream;Stream //
.range(1, 10)
.flatMap(n -> Stream
.range(1, n)
.reduce(0, (a, b) -> a + b))
.mapWithIndex(1)
.println()
.forEach();
```output:
```
Indexed[index=1, value=1]
Indexed[index=2, value=3]
Indexed[index=3, value=6]
Indexed[index=4, value=10]
Indexed[index=5, value=15]
Indexed[index=6, value=21]
Indexed[index=7, value=28]
Indexed[index=8, value=36]
Indexed[index=9, value=45]
Indexed[index=10, value=55]
```## Time-based operators
This library has a number of time-based operators. For example `Single.timer("a", 1, TimeUnit.SECONDS).get()` emits `a` one second after starting.Use of time-based operators is not optimal for production code because the current thread is blocked (by a `Thread.sleep`). If you are happy to wear a bit of extra complexity but win on efficiency then use `RxJava` for this scenario.
The time-based operators are:
* `Single.timer`
* `Stream.interval`
* `Stream.retryWhen`
* `Stream.delayStart`## RetryWhen
The `retryWhen` operator differs subtly from the RxJava implementation in that when no more retries will occur the last error is emitted (thrown, possibly wrapped to make unchecked). The operator has a helpful builder for common scenarios:### Limit retries
```java
stream
.retryWhen()
.maxRetries(10)
.build()
.forEach();
```
### Set delay between retries
```java
stream
.retryWhen()
.maxRetries(6)
.delay(5, TimeUnit.SECONDS)
.build()
.forEach();
```### Set variable delay between retries
Let's do capped exponential back-off:
```java
stream
.retryWhen()
.delays(Stream.of(1L, 2L, 4L, 8L, 16L, 30L).repeatLast(), TimeUnit.SECONDS)
.build()
.forEach();
```### RetryWhen example
Let's count the bytes read from a URL and perform retries:```java
URL url = new URL("https://doesnotexist.zz");
Stream
// ensure streams are closed after use or error
.using(() -> url.openStream(), in -> Stream.bytes(in))
.doOnStart(() -> System.out.println("starting at " + System.currentTimeMillis()))
.retryWhen()
// sleep between retries
.delays(Stream.of(1L, 2L, 4L), TimeUnit.SECONDS)
.build()
// count bytes read
.reduce(0, (n, bytes)-> n + bytes.length)
// if error then log
.doOnError(e -> System.out.println(e.getMessage()))
// if success then log number of bytes
.doOnValue(n -> System.out.println("bytes read=" + n))
// we choose to suppress exception
.switchOnError(e -> Single.of(-1))
// start (go, forEach or start)
.go();
```
output:
```
starting at 1544663193348
starting at 1544663194657
starting at 1544663196658
starting at 1544663200659
java.net.UnknownHostException: doesnotexist.zz
```
## Statistics
Give a stream of numbers you can calculate common statistics like count, mean, standard deviation, variance, kurtosis, skewness, range, min, max:```java
Statistics stats = Stream.of(1, 2, 6)
.statistics(x -> x)
.get();
System.out.println(stats.toString("", "\n"));
```
output
```
count=3
mean=3.0
standardDeviation=2.1602468994692865
variance=4.666666666666665
kurtosis=1.5
skewness=0.5951700641394974
min=1.0
max=6.0
range=5.0
```## JSON support
See [kool-json](kool-json).## Origin of the name
Functional programming -> Funk -> Kool and the Gang -> Kool!## Benchmarks
JMH is used for benchmarks.The Shakespeare Plays Scrabble benchmark uses the following factories and operators: `of`, `from`, `chars`, `map`, `flatMap`, `collect`, `reduce`, `take`, `filter`, `concatWith`, `groupByList`, `toList`.
## Checklist for new operators
* use `it.nextNullChecked()` instead of `it.next()` and `stream.iteratorNullChecked()` instead of `stream.iterator()`
* wrap calls to function parameters passed to operator with `Preconditions.checkNotNull` where appropriate
* dispose upstream iterables as soon as no longer required (but only if a call to dispose from downstream does not ensue immediately)
* set upstream iterable reference to null (to help gc) when no longer required