{"id":16782663,"url":"https://github.com/davidmoten/kool","last_synced_at":"2025-04-10T21:22:55.556Z","repository":{"id":33711735,"uuid":"145659250","full_name":"davidmoten/kool","owner":"davidmoten","description":"j.u.s.Stream alternative (synchronous only), reusable, faster, more operators, easier to use.","archived":false,"fork":false,"pushed_at":"2024-10-29T09:49:52.000Z","size":1040,"stargazers_count":16,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-29T11:50:46.387Z","etag":null,"topics":["functional-programming","java","method-chaining","stream","synchronous"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidmoten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-22T05:13:42.000Z","updated_at":"2024-10-29T09:49:49.000Z","dependencies_parsed_at":"2023-10-15T05:14:48.018Z","dependency_job_id":"9640013f-cd64-47ec-90b4-c8c9b648657f","html_url":"https://github.com/davidmoten/kool","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmoten%2Fkool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmoten%2Fkool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmoten%2Fkool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidmoten%2Fkool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidmoten","download_url":"https://codeload.github.com/davidmoten/kool/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248299108,"owners_count":21080464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","java","method-chaining","stream","synchronous"],"created_at":"2024-10-13T07:47:18.179Z","updated_at":"2025-04-10T21:22:55.539Z","avatar_url":"https://github.com/davidmoten.png","language":"Java","readme":"# kool\n\u003ca href=\"https://github.com/davidmoten/kool/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/davidmoten/kool/actions/workflows/ci.yml/badge.svg\"/\u003e\u003c/a\u003e\u003cbr/\u003e\n[![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)\u003cbr/\u003e\n[![codecov](https://codecov.io/gh/davidmoten/kool/branch/master/graph/badge.svg)](https://codecov.io/gh/davidmoten/kool)\n\n\nFaster and more powerful alternative to `java.util.stream.Stream` for synchronous use:\n\n* is sometimes much faster for synchonronous use ([benchmarks](benchmarks.md))\n* has many [more operators](https://davidmoten.github.io/kool/apidocs/org/davidmoten/kool/Stream.html) and is generally **less verbose**\n* operators are **more discoverable**\n* streams are **reusable**\n* **disposes** resources\n* is designed for **synchronous use only**\n* models **0..1** and **1** element streams explicitly with **`Maybe`** and **`Single`**.\n* does not support streams of nulls (use `Optional` or `Maybe`)\n* 30% **faster** on *Shakespeare Plays Scrabble* [benchmark](benchmarks.md)\n* has **time-based** operators\n* has statistics operator (reduction) that offers count, mean, sd, variance, kurtosis, skewness, min, max, range \n\nStatus: *available on Maven Central* \n\nMaven site reports are [here](https://davidmoten.github.io/kool) including [javadoc](https://davidmoten.github.io/kool/apidocs/index.html).\n\nIf you need non-blocking and/or asynchronous streaming use [RxJava](https://github.com/ReactiveX/RxJava).\n\nNote 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`.\n\n## How to build\n```bash\nmvn clean install\n```\n\n## Getting started\nAdd this dependency to your pom.xml:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.davidmoten\u003c/groupId\u003e\n    \u003cartifactId\u003ekool\u003c/artifactId\u003e\n    \u003cversion\u003eVERSION_HERE\u003c/version\u003e\n\u003c/dependency\u003e\n```\n### Operators\nSee this [list](https://davidmoten.github.io/kool/apidocs/org/davidmoten/kool/Stream.html).\n\n## Example\n```java\nimport org.davidmoten.kool.Stream;\n\nStream //\n  .range(1, 10)\n  .flatMap(n -\u003e Stream\n      .range(1, n)\n      .reduce(0, (a, b) -\u003e a + b))\n  .mapWithIndex(1)\n  .println()\n  .forEach();\n```\n\noutput:\n```\nIndexed[index=1, value=1]\nIndexed[index=2, value=3]\nIndexed[index=3, value=6]\nIndexed[index=4, value=10]\nIndexed[index=5, value=15]\nIndexed[index=6, value=21]\nIndexed[index=7, value=28]\nIndexed[index=8, value=36]\nIndexed[index=9, value=45]\nIndexed[index=10, value=55]\n```\n\n## Time-based operators\nThis library has a number of time-based operators. For example `Single.timer(\"a\", 1, TimeUnit.SECONDS).get()` emits `a` one second after starting. \n\nUse 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.\n\nThe time-based operators are:\n* `Single.timer`\n* `Stream.interval`\n* `Stream.retryWhen`\n* `Stream.delayStart`\n\n## RetryWhen\nThe `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:\n\n### Limit retries\n```java\nstream\n  .retryWhen()\n  .maxRetries(10)\n  .build()\n  .forEach();\n```\n### Set delay between retries\n```java\nstream\n  .retryWhen()\n  .maxRetries(6)\n  .delay(5, TimeUnit.SECONDS)\n  .build()\n  .forEach();\n```\n\n### Set variable delay between retries\nLet's do capped exponential back-off:\n```java\nstream\n  .retryWhen()\n  .delays(Stream.of(1L, 2L, 4L, 8L, 16L, 30L).repeatLast(), TimeUnit.SECONDS)\n  .build()\n  .forEach();\n```\n\n### RetryWhen example\nLet's count the bytes read from a URL and perform retries:\n\n```java\nURL url = new URL(\"https://doesnotexist.zz\");\nStream\n  // ensure streams are closed after use or error\n  .using(() -\u003e url.openStream(), in -\u003e Stream.bytes(in))\n  .doOnStart(() -\u003e System.out.println(\"starting at \" + System.currentTimeMillis())) \n  .retryWhen() \n  // sleep between retries\n  .delays(Stream.of(1L, 2L, 4L), TimeUnit.SECONDS)\n  .build() \n  // count bytes read\n  .reduce(0, (n, bytes)-\u003e n + bytes.length) \n  // if error then log\n  .doOnError(e -\u003e System.out.println(e.getMessage())) \n  // if success then log number of bytes\n  .doOnValue(n -\u003e System.out.println(\"bytes read=\" + n)) \n  // we choose to suppress exception\n  .switchOnError(e -\u003e Single.of(-1))\n  // start (go, forEach or start) \n  .go();\n```\noutput:\n```\nstarting at 1544663193348\nstarting at 1544663194657\nstarting at 1544663196658\nstarting at 1544663200659\njava.net.UnknownHostException: doesnotexist.zz\n```\n## Statistics\nGive a stream of numbers you can calculate common statistics like count, mean, standard deviation, variance, kurtosis, skewness, range, min, max:\n\n```java\nStatistics stats = Stream.of(1, 2, 6)\n  .statistics(x -\u003e x)\n  .get();\nSystem.out.println(stats.toString(\"\", \"\\n\"));\n```\noutput\n```\ncount=3\nmean=3.0\nstandardDeviation=2.1602468994692865\nvariance=4.666666666666665\nkurtosis=1.5\nskewness=0.5951700641394974\nmin=1.0\nmax=6.0\nrange=5.0\n```\n\n## JSON support\nSee [kool-json](kool-json).\n\n## Origin of the name\nFunctional programming -\u003e Funk -\u003e Kool and the Gang -\u003e Kool!\n\n## Benchmarks\nJMH is used for benchmarks. \n\nThe Shakespeare Plays Scrabble benchmark uses the following factories and operators: `of`, `from`, `chars`, `map`, `flatMap`, `collect`, `reduce`, `take`, `filter`, `concatWith`, `groupByList`, `toList`.\n\n## Checklist for new operators\n* use `it.nextNullChecked()` instead of `it.next()` and `stream.iteratorNullChecked()` instead of `stream.iterator()`\n* wrap calls to function parameters passed to operator with `Preconditions.checkNotNull` where appropriate\n* dispose upstream iterables as soon as no longer required (but only if a call to dispose from downstream does not ensue immediately)\n* set upstream iterable reference to null (to help gc) when no longer required\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidmoten%2Fkool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidmoten%2Fkool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidmoten%2Fkool/lists"}