{"id":15030443,"url":"https://github.com/annimon/lightweight-stream-api","last_synced_at":"2025-05-15T00:14:11.456Z","repository":{"id":25266359,"uuid":"28691699","full_name":"aNNiMON/Lightweight-Stream-API","owner":"aNNiMON","description":"Stream API from Java 8 rewritten on iterators for Java 7 and below","archived":false,"fork":false,"pushed_at":"2024-02-20T21:19:26.000Z","size":1863,"stargazers_count":1600,"open_issues_count":0,"forks_count":127,"subscribers_count":42,"default_branch":"master","last_synced_at":"2025-05-15T00:14:02.710Z","etag":null,"topics":["backports","functional-programming","java","stream-api"],"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/aNNiMON.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":"2015-01-01T17:43:41.000Z","updated_at":"2025-04-26T00:24:10.000Z","dependencies_parsed_at":"2024-06-18T22:54:32.023Z","dependency_job_id":"d2057b60-d2a7-4e99-9b0a-c578b22806b5","html_url":"https://github.com/aNNiMON/Lightweight-Stream-API","commit_stats":{"total_commits":524,"total_committers":27,"mean_commits":19.40740740740741,"dds":0.4370229007633588,"last_synced_commit":"1d777f12f00595f6a50e2b0bee9d74477f2965b2"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aNNiMON%2FLightweight-Stream-API","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aNNiMON%2FLightweight-Stream-API/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aNNiMON%2FLightweight-Stream-API/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aNNiMON%2FLightweight-Stream-API/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aNNiMON","download_url":"https://codeload.github.com/aNNiMON/Lightweight-Stream-API/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254249206,"owners_count":22039029,"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":["backports","functional-programming","java","stream-api"],"created_at":"2024-09-24T20:13:21.933Z","updated_at":"2025-05-15T00:14:06.436Z","avatar_url":"https://github.com/aNNiMON.png","language":"Java","readme":"Lightweight-Stream-API\n======================\n\n[![Coverage Status](https://coveralls.io/repos/aNNiMON/Lightweight-Stream-API/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/aNNiMON/Lightweight-Stream-API?branch=master)\n[![SonarCloud Status](https://sonarcloud.io/api/project_badges/measure?project=lightweight-stream-api\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=lightweight-stream-api)\n[![SonarCloud Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=lightweight-stream-api\u0026metric=sqale_rating)](https://sonarcloud.io/dashboard/?id=lightweight-stream-api)  \n[![Build Status](https://travis-ci.org/aNNiMON/Lightweight-Stream-API.svg?branch=master)](https://travis-ci.org/aNNiMON/Lightweight-Stream-API)\n[![Maven Central](https://img.shields.io/maven-central/v/com.annimon/stream.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.annimon%22%20AND%20a%3A%22stream%22)\n[![javadoc](https://javadoc.io/badge2/com.annimon/stream/javadoc.svg)](https://javadoc.io/doc/com.annimon/stream)\n\nStream API from Java 8 rewritten on iterators for Java 7 and below.\n\n\n### Includes\n\n + Functional interfaces (`Supplier`, `Function`, `Consumer` etc);\n + `Stream`/`IntStream`/`LongStream`/`DoubleStream` (without parallel processing, but with a variety of additional methods and with custom operators);\n + `Optional`/`OptionalBoolean`/`OptionalInt`/`OptionalLong`/`OptionalDouble` classes;\n + `Exceptional` class - functional way to deal with exceptions;\n + `Objects` from Java 7.\n\n\n### Usage\n\n```java\nStream.of(/* array | list | set | map | anything based on Iterator/Iterable interface */)\n    .filter(..)\n    .map(..)\n    ...\n    .sorted()\n    .forEach(..);\nStream.of(value1, value2, value3)...\nIntStream.range(0, 10)...\n```\nExample project: https://github.com/aNNiMON/Android-Java-8-Stream-Example\n\n\n## Key features\n\n### Custom operators\n\nUnlike Java 8 streams, Lightweight-Stream-API provides the ability to apply custom operators.\n\n```java\nStream.of(...)\n    .custom(new Reverse\u003c\u003e())\n    .forEach(...);\n\npublic final class Reverse\u003cT\u003e implements UnaryOperator\u003cStream\u003cT\u003e\u003e {\n\n    @Override\n    public Stream\u003cT\u003e apply(Stream\u003cT\u003e stream) {\n        final Iterator\u003c? extends T\u003e iterator = stream.getIterator();\n        final ArrayDeque\u003cT\u003e deque = new ArrayDeque\u003cT\u003e();\n        while (iterator.hasNext()) {\n            deque.addFirst(iterator.next());\n        }\n        return Stream.of(deque.iterator());\n    }\n}\n```\n\nYou can find more examples [here](https://github.com/aNNiMON/Lightweight-Stream-API/blob/master/stream/src/test/java/com/annimon/stream/CustomOperators.java).\n\n### Additional operators\n\nIn addition to backported Java 8 Stream operators, the library provides:\n\n- `filterNot` - negated `filter` operator\n\n  ```java\n  // Java 8\n  stream.filter(((Predicate\u003cString\u003e) String::isEmpty).negate())\n  // LSA\n  stream.filterNot(String::isEmpty)\n  ```\n\n- `select` - filters instances of the given class\n\n  ```java\n  // Java 8\n  stream.filter(Integer.class::isInstance)\n  // LSA\n  stream.select(Integer.class)\n  ```\n\n- `withoutNulls` - filters only not null elements\n\n  ```java\n  Stream.of(\"a\", null, \"c\", \"d\", null)\n      .withoutNulls() // [a, c, d]\n  ```\n\n- `sortBy` - sorts by extractor function\n\n  ```java\n  // Java 8\n  stream.sorted(Comparator.comparing(Person::getName))\n  // LSA\n  stream.sortBy(Person::getName)\n  ```\n\n- `groupBy` - groups by extractor function\n\n  ```java\n  // Java 8\n  stream.collect(Collectors.groupingBy(Person::getName)).entrySet().stream()\n  // LSA\n  stream.groupBy(Person::getName)\n  ```\n\n- `chunkBy` - partitions sorted stream by classifier function\n\n  ```java\n  Stream.of(\"a\", \"b\", \"cd\", \"ef\", \"gh\", \"ij\", \"klmnn\")\n      .chunkBy(String::length) // [[a, b], [cd, ef, gh, ij], [klmnn]]\n  ```\n\n- `sample` - emits every n-th elements\n\n  ```java\n  Stream.rangeClosed(0, 10)\n      .sample(2) // [0, 2, 4, 6, 8, 10]\n  ```\n\n- `slidingWindow` - partitions stream into fixed-sized list and sliding over the elements\n\n  ```java\n  Stream.rangeClosed(0, 10)\n      .slidingWindow(4, 6) // [[0, 1, 2, 3], [6, 7, 8, 9]]\n  ```\n\n- `takeWhile` / `dropWhile` - introduced in Java 9, limits/skips stream by predicate function\n\n  ```java\n  Stream.of(\"a\", \"b\", \"cd\", \"ef\", \"g\")\n      .takeWhile(s -\u003e s.length() == 1) // [a, b]\n  Stream.of(\"a\", \"b\", \"cd\", \"ef\", \"g\")\n      .dropWhile(s -\u003e s.length() == 1) // [cd, ef, g]\n  ```\n\n- `scan` - iteratively applies accumulation function and returns Stream\n\n  ```java\n  IntStream.range(1, 6)\n      .scan((a, b) -\u003e a + b) // [1, 3, 6, 10, 15]\n  ```\n\n- `indexed` - adds an index to every element, result is `IntPair`\n\n  ```java\n  Stream.of(\"a\", \"b\", \"c\")\n      .indexed() // [(0 : \"a\"), (1 : \"b\"), (2 : \"c\")]\n  ```\n\n- `filterIndexed` / `mapIndexed` / `takeWhileIndexed` / `takeUntilIndexed` / `dropWhileIndexed` / `reduceIndexed` / `forEachIndexed` - indexed specialization of operators\n\n  ```java\n  Stream.of(\"a\", \"b\", \"c\")\n      .mapIndexed((i, s) -\u003e s + Integer.toString(i)) // [a0, b1, c2]\n  ```\n\n\n### Throwable functions\n\nNo more ugly try/catch in lambda expressions.\n\n```java\n// Java 8\nstream.map(file -\u003e {\n    try {\n        return new FileInputStream(file);\n    } catch (IOException ioe) {\n        return null;\n    }\n})\n// LSA\nstream.map(Function.Util.safe(FileInputStream::new))\n```\n\n\n## Download\n\nDownload [latest release](https://github.com/aNNiMON/Lightweight-Stream-API/releases) or grab via Maven:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.annimon\u003c/groupId\u003e\n  \u003cartifactId\u003estream\u003c/artifactId\u003e\n  \u003cversion\u003e1.2.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\nor Gradle:\n\n```groovy\ndependencies {\n  ...\n  implementation 'com.annimon:stream:1.2.2'\n  ...\n}\n```\n\nor use latest unrealeased features with [JitPack](https://jitpack.io/#aNNiMON/Lightweight-Stream-API).\n\nAlso included version for **Java ME**. Checkout [javame branch](https://github.com/aNNiMON/Lightweight-Stream-API/tree/javame).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fannimon%2Flightweight-stream-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fannimon%2Flightweight-stream-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fannimon%2Flightweight-stream-api/lists"}