{"id":13713360,"url":"https://github.com/jucardi/go-streams","last_synced_at":"2026-04-02T02:07:31.870Z","repository":{"id":37276444,"uuid":"93830586","full_name":"jucardi/go-streams","owner":"jucardi","description":"Stream Collections for Go. Inspired in Java 8 Streams and .NET Linq","archived":false,"fork":false,"pushed_at":"2026-03-09T23:07:24.000Z","size":94,"stargazers_count":329,"open_issues_count":4,"forks_count":27,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-03-10T05:18:49.704Z","etag":null,"topics":["array","collection","collections","filter","foreach","go","go-streams","golang","iterables","java-streams","linq","slice","stream","stream-collections","stream-match","stream-pipeline","streams"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jucardi.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":"2017-06-09T07:17:42.000Z","updated_at":"2026-03-09T23:06:57.000Z","dependencies_parsed_at":"2024-05-13T00:43:34.790Z","dependency_job_id":null,"html_url":"https://github.com/jucardi/go-streams","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/jucardi/go-streams","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-streams","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-streams/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-streams/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-streams/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jucardi","download_url":"https://codeload.github.com/jucardi/go-streams/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jucardi%2Fgo-streams/sbom","scorecard":{"id":540759,"data":{"date":"2025-08-11","repo":{"name":"github.com/jucardi/go-streams","commit":"5e2a80b57b46e912ead58ebf2d6fe80e773a8ea8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":0,"reason":"Found 1/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T08:09:09.359Z","repository_id":37276444,"created_at":"2025-08-20T08:09:09.359Z","updated_at":"2025-08-20T08:09:09.359Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31294398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T01:43:37.129Z","status":"online","status_checked_at":"2026-04-02T02:00:08.535Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["array","collection","collections","filter","foreach","go","go-streams","golang","iterables","java-streams","linq","slice","stream","stream-collections","stream-match","stream-pipeline","streams"],"created_at":"2024-08-02T23:01:33.815Z","updated_at":"2026-04-02T02:07:31.860Z","avatar_url":"https://github.com/jucardi.png","language":"Go","funding_links":[],"categories":["Repositories"],"sub_categories":[],"readme":"## Stream Collections for Go, inspired in Java 8 Streams and .NET Linq\n\nThis library provides\n- structs to easily represent and manage collections and iterable of elements which size are not necessarily defined.\n- Stream structs to support functional-style operations on streams of elements, such as map-reduce transformations on \ncollections, filtering, sorting, mapping, foreach parallel operations.\n\n---\n***(Nov 2022) Important Update:** This library has been redesigned to support **Golang Generics**, and it is not backwards \ncompatible with the previous version. Also requires at least Go 1.18. If you require the older version without generics \nor a version that is compatible with an older version of Go, using Golang Modules you may get the latest stable version\nwithout generics by running the following command:*\n\n```bash\ngo get github.com/jucardi/go-streams@v1.0.3\n```\n---\n\n##### Quick Start\n\nTo keep up to date with the most recent version:\n\n```bash\ngo get github.com/jucardi/go-streams\n```\n\nUsing Golang Modules\n```bash\ngo get github.com/jucardi/go-streams/v2@latest\n```\n\nFor the latest version without Golang Generics (v1.0.3)\n```bash\ngo get github.com/jucardi/go-streams@v1.0.3\n```\n\n##### Quick Overview\n\nStreams facilitate operations on arrays, iterables and collections, such as *filtering*, *sorting*, *mapping*, *foreach*, and parallel operations on the items contained by these arrays, iterables or collections\n\n**A quick example:**\n\nGiven the following array\n\n```Go\nvar fruitArray = []string{\"peach\", \"apple\", \"pear\", \"plum\", \"pineapple\", \"banana\", \"kiwi\", \"orange\"}\n```\n\nLet's obtain an array of only the elements that start with the letter \"p\"\n\n```go\nfruitsThatStartWithP := streams.\n\n    // Creates a stream from the given array\n    From[string](fruitArray).\n\n    // Adds a filter for strings that start with 'p'\n    Filter(func(v string) bool {\n        return strings.HasPrefix(v, \"p\")\n    }).\n\n    // Sorts alphabetically\n    Sort(strings.Compare).\n\n    // Converts back to an array\n    ToArray()\n```\nThe resulting array will be `{\"peach\", \"pear\", \"pineapple\", \"plum\"}`\n\nHere we use an array of string as the source of the stream, perform a filter operation provided by a function that\nreceives a single element of the collection and determines whether the element should remain in the stream by returning\na boolean.\n\nNow let's do a simple foreach operation\n\n```go\nstreams.\n    From[string](fruitArray).\n    Filter(func(v string) bool {\n        return strings.HasPrefix(v, \"p\")\n    }).\n    ForEach(func(v string) {\n        println(v)\n    })\n```\n\nIn this example, once the stream processes the filter, performs a foreach operation with the result. With this operation\nwe'll obtain the following output in the console\n\n```\npeach\npear\nplum\npineapple\n```\n\n## About the go-streams\n\nThe characteristics of a Stream are inspired in the stream features provided by Java 8. The following characteristics \napply in the go-streams.\n\n- No storage. A stream is not a data structure that stores elements; instead, it conveys elements from a source such as \na data structure, an array, a generator function, or an I/O channel, through a pipeline of computational operations.\n- Functional in nature. An operation on a stream produces a result, but does not modify its source. For example,\nfiltering a Stream obtained from a collection produces a new Stream without the filtered elements, rather than removing\nelements from the source collection.\n- Laziness-seeking. Many stream operations, such as filtering and sorting, can be implemented lazily, exposing\nopportunities for optimization. For example, \"find the first String with three consecutive vowels\" need not examine all\nthe input strings. Stream operations are divided into intermediate (Stream-producing) operations and terminal (value- or\nside-effect-producing) operations. Intermediate operations are always lazy.\n- Consumable. The elements of a stream are only visited once during the life of a stream. Like an Iterator, a new stream\nmust be generated to revisit the same elements of the source.\n\nCurrently Streams can be obtained in several ways:\n- From an array via `streams.FromArray[T comparable](array []T)`\n- From an implementation of `streams.ICollection[T comparable]` via `streams.FromCollection[T comparable](col ICollection[T])`\n- From a map via `streams.FromMap[K comparable, V any](m map[K]V)`\n- Using the generic `streams.From[T comparable](set any)` which accepts arrays or collections\n\n## Stream operations and pipelines\n\nStream operations are divided into intermediate and terminal operations, and are combined to form stream pipelines. A \nstream pipeline consists of a source (such as an iterable, a collection, an array, a generator function, or an I/O \nchannel); followed by zero or more intermediate operations such as `Filter()`, `Except()` or `Sort()` and a terminal\noperation such as `ForEach()` or `First()`\n\nIntermediate operations return a stream. They are always lazy; executing an intermediate operation such as `Filter()`\nor `Sort()` does not actually perform any action, but instead register the action into the stream that, when traversed,\nwill execute all filtering and sorting criteria at once. Traversal of the pipeline source does not begin until the\nterminal operation of the pipeline is executed, such as `First()`, `Last()`, `ToArray()`, `ForEach()`\n\nTerminal operations, such as `ForEach()`, `First()`, `Last()`, `ParallelForEach()` or `ToArray()`, may traverse the\nstream to produce a result or a side-effect. After the terminal operation is performed, the stream pipeline is\nconsidered consumed, and can no longer be used; if you need to traverse the same data source again, you must return to\nthe data source to get a new stream. In almost all cases, terminal operations are eager, completing their traversal of\nthe data source and processing of the pipeline before returning\n\n### Intermediate operations\n\n- `Filter(f func(x T) bool)`: Filters any element that does not meet the condition provided by the function.\n- `Except(f func(x T) bool)`: Filters all elements that meet the condition provided by the function.\n- `Sort(f func(x, y T) int, desc ...bool)`: Sorts the elements in the stream using the provided comparable function.\n- `SetThreads(threads int)`: Sets the number of threads to be used when processing the stream.\n- `Distinct()`: Ensures that the resulting stream operation only includes unique values.\n- `Skip(n int)`: Discards the first `n` elements from the resulting stream and returns a new stream with the remaining\n  elements.\n- `Limit(n int)`: Returns a new stream containing at most `n` elements from the resulting stream.\n- `Reverse()`: Returns a new stream with the elements in reverse order.\n- `Peek(f func(x T))`: Performs the provided action on each element without consuming the stream, returning a new stream\n  with the same elements. Useful for debugging or logging.\n- `TakeWhile(f func(x T) bool)`: Returns a new stream containing elements from the start as long as the condition\n  returns true. Stops at the first element that does not match.\n- `SkipWhile(f func(x T) bool)`: Skips elements from the start as long as the condition returns true, then returns a\n  new stream with all remaining elements.\n\n\n### Terminal operations\n\n###### Single item returns\n- `First(defaultValue ...T)`: Returns the first element of the resulting stream. Returns default T (or defaultValue if\nprovided) if the resulting stream is empty.\n- `Last(defaultValue ...T)`: Returns the last element of the resulting stream. Returns default T (or defaultValue if\nprovided) if the resulting stream is empty.\n- `At(i int, defaultValue ...T)`: Returns the element at the given index in the resulting stream. Returns default T (or\ndefaultValue if provided) if out of bounds.\n- `AtReverse(i int, defaultValue ...T)`: Returns the element at the given position, starting from the last element to\nthe first in the resulting stream. Returns default T (or defaultValue if provided) if out of bounds.\n\n###### Collection returns\n- `ToArray()`: Returns an array of elements from the resulting stream.\n- `ToCollection()`: Returns a `ICollection[T]` of elements from the resulting stream.\n- `ToIterable()`: Returns a `IIterable[T]` of elements from the resulting stream.\n- `ToList()`: Returns a `IList[T]` of elements from the resulting stream.\n- `ToDistinct()`: Returns a `ISet[T]` of elements from the resulting stream with only unique values.\n- `Chunk(size int)`: Splits the stream into slices of the given size and returns them as a `[][]T`.\n\n###### Boolean returns\n- `IsEmpty()`: Indicates whether the resulting stream contains no elements.\n- `Contains(value T)`: Indicates whether the provided value matches any of the values in the stream.\n- `AnyMatch(f func(x T) bool)`: Indicates whether ANY elements of the stream match the given condition function.\n- `AllMatch(f func(x T) bool)`: Indicates whether ALL elements of the stream match the given condition function.\n- `NotAllMatch(f func(x T) bool)`: The negation of `AllMatch`. If any of the elements do not match the provided\ncondition the result will be `true`; `false` otherwise.\n- `NoneMatch(f func(x T) bool)`: Indicates whether NONE of elements of the stream match the given condition\nfunction.\n\n###### IThen[T] returns\n\n`IThen[T]` is a handler where functions can be registered and triggered if the stream result meets a certain condition\n\n**E.g:**\n```go\nstreams.\n    FromArray[T](array). \n    Filter(filterHandler).\n    Filter(anotherFilterHandle).\n    Sort(sorterHandler).\n    IfEmpty().\n    Then(func(resultStream IStream[T]) { \n        // Do something if empty\n    }).\n    Else(func(resultStream IStream[T]) { \n        // Do something if not empty\n    })\n```\n\n- `IfEmpty()`: Returns a `IThen[T]` handler if empty.\n- `IfAnyMatch(f ConditionalFunc[T])`: Returns a `IThen[T]` handler if any elements match the provided condition.\n- `IfAllMatch(f ConditionalFunc[T])`: Returns a `IThen[T]` handler if all elements match the provided condition.\n- `IfNoneMatch(f ConditionalFunc[T])`: Returns a `IThen[T]` handler if no elements match the provided condition.\n\n###### Void returns\n- `ForEach(f func(x T))`: Iterates over all elements in the stream calling the provided function.\n- `ParallelForEach(f func(x T), threads int, skipWait ...bool)`: Iterates over all elements in the stream calling the provided\nfunction. Creates multiple go channels to parallelize the operation. ParallelForeach does not use any thread values \npreviously provided in any filtering method nor enables parallel filtering if any filtering is done prior to the \n`ParallelForEach` phase. Only use `ParallelForEach` if the order in which the elements are processed does not matter, \notherwise see `ForEach`.\n\n###### Int returns\n- `Count()`: Counts the elements contained by the resulting stream.\n\n### Standalone functions\n\nThese functions operate on sources (arrays, collections, iterators, or streams) and produce results. They are standalone\nbecause Go generics do not allow adding additional type parameters to methods on interfaces/structs.\n\n#### Mapping functions\n\n- `Map[From, To comparable](source any, f ConvertFunc[From, To]) IList[To]`: Maps the elements of the source to new\nelements using the mapping function. Outputs a new `IList` with the converted elements. Accepted sources: `[]From`,\n`IIterable[From]`, `IIterator[From]`, `IStream[From]`.\n\n- `MapNonComparable[From, To any](source any, f ConvertFunc[From, To]) []To`: Similar to `Map`, but outputs an array\nand accepts non-comparable types. Accepted sources: `[]From`, `IIterable[From]`, `IIterator[From]`.\n\n- `MapToPtr[T any](source any) []*T`: Converts a collection of `T` to `[]*T`. Useful for non-comparable structs since\npointers are always comparable and can be used with `IStream`, `ICollection`, etc.\n\n#### Reduce / Aggregate\n\n- `Reduce[T comparable](source any, identity T, f func(T, T) T) T`: Folds all elements into a single value using the\naccumulator function, starting from the identity value.\n\n```go\nsum := streams.Reduce[int]([]int{1, 2, 3, 4}, 0, func(acc, x int) int { return acc + x })\n// sum = 10\n```\n\n- `ReduceAny[T comparable, R any](source any, identity R, f func(R, T) R) R`: Like `Reduce` but allows the accumulator\nto be a different type than the elements.\n\n```go\ncsv := streams.ReduceAny[int, string]([]int{1, 2, 3}, \"\", func(acc string, x int) string {\n    if acc != \"\" { acc += \",\" }\n    return acc + strconv.Itoa(x)\n})\n// csv = \"1,2,3\"\n```\n\n#### FlatMap\n\n- `FlatMap[From, To comparable](source any, f func(From) []To) IList[To]`: Maps each element to a slice and flattens\nthe results into a single `IList`.\n\n```go\nresult := streams.FlatMap[string, string]([]string{\"hello\", \"world\"}, func(s string) []string {\n    var chars []string\n    for _, c := range s { chars = append(chars, string(c)) }\n    return chars\n})\n// result contains [\"h\", \"e\", \"l\", \"l\", \"o\", \"w\", \"o\", \"r\", \"l\", \"d\"]\n```\n\n#### Concat\n\n- `Concat[T comparable](sources ...any) IStream[T]`: Concatenates multiple sources (arrays, collections, or streams)\ninto a single stream.\n\n```go\nresult := streams.Concat[int]([]int{1, 2}, []int{3, 4}).ToArray()\n// result = [1, 2, 3, 4]\n```\n\n#### Zip\n\n- `Zip[A, B, R comparable](sourceA any, sourceB any, f func(A, B) R) IList[R]`: Combines two sources element-wise\nusing the provided function. Stops at the shorter source.\n\n```go\nresult := streams.Zip[int, string, string](\n    []int{1, 2, 3},\n    []string{\"a\", \"b\", \"c\"},\n    func(i int, s string) string { return strconv.Itoa(i) + s },\n)\n// result contains [\"1a\", \"2b\", \"3c\"]\n```\n\n#### GroupBy\n\n- `GroupBy[T comparable, K comparable](source any, keyFn func(T) K) map[K][]T`: Groups the elements by a key function,\nreturning a map of key to slices.\n\n```go\nresult := streams.GroupBy[string, string](\n    []string{\"apple\", \"avocado\", \"banana\", \"blueberry\"},\n    func(s string) string { return string(s[0]) },\n)\n// result = {\"a\": [\"apple\", \"avocado\"], \"b\": [\"banana\", \"blueberry\"]}\n```\n\n#### DistinctBy\n\n- `DistinctBy[T comparable, K comparable](source any, keyFn func(T) K) IList[T]`: Returns a new `IList` with duplicates\nremoved based on a key function.\n\n```go\nresult := streams.DistinctBy[string, byte](\n    []string{\"apple\", \"avocado\", \"banana\"},\n    func(s string) byte { return s[0] },\n)\n// result contains [\"apple\", \"banana\"] (first occurrence per key)\n```\n\n#### Aggregation functions\n\n- `Min[T comparable](source any, less func(T, T) bool) (T, bool)`: Returns the minimum element using the provided\ncomparison function. Returns `(zeroValue, false)` if the source is empty.\n\n- `Max[T comparable](source any, less func(T, T) bool) (T, bool)`: Returns the maximum element using the provided\ncomparison function. Returns `(zeroValue, false)` if the source is empty.\n\n- `Sum[T INumeric](source any) T`: Returns the sum of all numeric elements. `INumeric` includes `int`, `int8`, `int16`,\n`int32`, `int64`, `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `float32`, `float64`.\n\n- `Average[T INumeric](source any) (float64, bool)`: Returns the average of all numeric elements as `float64`. Returns\n`(0, false)` if the source is empty.\n\n```go\nmin, _ := streams.Min[int]([]int{5, 3, 8, 1}, func(a, b int) bool { return a \u003c b })\n// min = 1\n\nmax, _ := streams.Max[int]([]int{5, 3, 8, 1}, func(a, b int) bool { return a \u003c b })\n// max = 8\n\nsum := streams.Sum[int]([]int{1, 2, 3, 4, 5})\n// sum = 15\n\navg, _ := streams.Average[int]([]int{10, 20, 30})\n// avg = 20.0\n```\n\n#### Set operations\n\n- `Union[T comparable](sourceA, sourceB any) IList[T]`: Returns a new `IList` containing the distinct union of elements\nfrom both sources, preserving order of first appearance.\n\n- `Intersect[T comparable](sourceA, sourceB any) IList[T]`: Returns a new `IList` containing elements that are present\nin both sources.\n\n```go\nunion := streams.Union[int]([]int{1, 2, 3}, []int{3, 4, 5})\n// union contains [1, 2, 3, 4, 5]\n\nintersect := streams.Intersect[int]([]int{1, 2, 3}, []int{2, 3, 4})\n// intersect contains [2, 3]\n```\n\n#### Factory functions\n\n- `Range(start, end int) IStream[int]`: Creates a stream of integers from `start` (inclusive) to `end` (exclusive).\n\n- `Repeat[T comparable](value T, n int) IStream[T]`: Creates a stream containing the given value repeated `n` times.\n\n```go\nrangeStream := streams.Range(0, 5).ToArray()\n// [0, 1, 2, 3, 4]\n\nrepeatStream := streams.Repeat[string](\"hello\", 3).ToArray()\n// [\"hello\", \"hello\", \"hello\"]\n```\n\n#### Sorting utilities\n\n- `Sort[T ISortable](arr []T, desc ...bool)`: Sorts a slice of comparable types in-place. `ISortable` includes all\nnumeric types and `string`.\n\n- `ComparableFn[T ISortable](desc ...bool) SortFunc[T]`: Creates a `SortFunc[T]` for built-in sortable types that can\nbe used with `IStream.Sort()`.\n\n```go\narr := []int{5, 3, 1, 4, 2}\nstreams.Sort(arr) // arr is now [1, 2, 3, 4, 5]\n\nsorted := streams.From[int](arr).Sort(streams.ComparableFn[int]()).ToArray()\n```\n\n#### Predefined mappers\n\nAccess built-in conversion functions via `Mappers()`:\n\n- `Mappers().IntToString()`: Returns a `ConvertFunc[int, string]`.\n- `Mappers().StringToInt(errorHandler ...func(string, error))`: Returns a `ConvertFunc[string, int]`. Optionally accepts\nan error handler for invalid conversions.\n\n```go\nintArr := streams.Map[string, int](\n    []string{\"1\", \"2\", \"3\"},\n    streams.Mappers().StringToInt(),\n)\n```\n\n### Parallelism\n\nParallel operations are allowed with the streams, once enabled, when the intermediate operations are processed, they\nwill be done in parallel. Note that parallelism for `ForEach` operations are handled separately, since `ForEach` is a\nterminal operation and executing it in parallel cannot guarantee the final order of the intermediate operations.\n\n###### Enabling parallelism for intermediate operations.\n\nThere are multiple ways of enabling parallelism in a stream.\n\n- As a variadic argument at the time of creation. (Supported by `From`, `FromArray` and `FromCollection`)\n\n```go\nstream := streams.\n    FromArray[T](array, 8).      // Creates the stream from the given array, the second (variadic) argument indicates \n                                 // the amount of threads to be used when executing intermediate operations\n    Filter(filterHandler).\n    Filter(anotherFilterHandle).\n    Sort(sorterHandler)\n```\n\n- Explicitly to the stream at any point before a terminal operation\n\n```go\nstream := streams.\n    FromArray[T](array).\n    SetThreads(8).           // Sets the amount of threads to be used when executing intermediate operations\n    Filter(filterHandler).\n    Except(exceptHandler).\n    Sort(sorterHandler)\n```\n\nWhen setting the amount of threads, the amount will be capped by the maximum number of CPUs available on the host\nmachine. Any number equal to or lower than `0` can be provided to use the maximum available threads.\n\n###### Executing a ForEach in parallel\n\nThe `ForEach` function by default does not run in parallel, regardless if threads were previously assigned for\nintermediate operations. The reason is that intermediate operations produce a result which may have been sorted.\nWhen running a `ForEach` in parallel, the order of execution cannot be guaranteed.\n\nUse `ParallelForEach` only when the order of execution does not matter.\n\n```go\nstream := streams.\n    FromArray[T](array, 8).\n    Filter(filterHandler).\n    Except(exceptHandler).\n    Sort(sorterHandler).\n    ParallelForEach(func(x T) {\n        // foreach logic here.\n    }, 0)                     // 0 = use maximum available cores\n```\n\n### Collections\n\nThis library provides several collection types:\n\n- `ICollection[T comparable]`: Base collection interface with `Add`, `Remove`, `Contains`, `Len`, `Clear`, `ToArray`,\n  `ForEach`, and iterator support.\n- `IList[T comparable]`: Extends `ICollection` with index-based access (`Index`, `RemoveAt`), `Distinct`, and `Stream`.\n- `ISet[T comparable]`: A collection that guarantees unique values.\n- `IMap[K comparable, V any]`: A map that also implements `IList[*KeyValuePair[K, V]]` with `Get`, `Set`, `ContainsKey`,\n  `Keys`, `Delete`, and `ToMap`.\n\n#### Creating collections\n\n```go\nlist := streams.NewList[int]([]int{1, 2, 3})\nset := streams.NewSet[int]()\nm := streams.NewMap[string, int](map[string]int{\"a\": 1, \"b\": 2})\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjucardi%2Fgo-streams","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjucardi%2Fgo-streams","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjucardi%2Fgo-streams/lists"}