{"id":20709622,"url":"https://github.com/go-andiamo/streams","last_synced_at":"2025-06-14T13:02:58.477Z","repository":{"id":64299087,"uuid":"568440187","full_name":"go-andiamo/streams","owner":"go-andiamo","description":"Golang implementation of streams","archived":false,"fork":false,"pushed_at":"2023-04-29T10:51:54.000Z","size":135,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-14T13:02:34.380Z","etag":null,"topics":["difference","generics","go","golang","intersection","stream","streams","symmetric-difference","union"],"latest_commit_sha":null,"homepage":"","language":"Go","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/go-andiamo.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":"2022-11-20T14:43:18.000Z","updated_at":"2023-09-01T23:13:54.000Z","dependencies_parsed_at":"2024-06-20T11:06:18.786Z","dependency_job_id":"30daa6d5-930e-454d-a8d3-95ab56e15ef9","html_url":"https://github.com/go-andiamo/streams","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/go-andiamo/streams","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-andiamo%2Fstreams","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-andiamo%2Fstreams/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-andiamo%2Fstreams/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-andiamo%2Fstreams/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-andiamo","download_url":"https://codeload.github.com/go-andiamo/streams/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-andiamo%2Fstreams/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259820788,"owners_count":22916544,"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":["difference","generics","go","golang","intersection","stream","streams","symmetric-difference","union"],"created_at":"2024-11-17T02:07:19.398Z","updated_at":"2025-06-14T13:02:58.417Z","avatar_url":"https://github.com/go-andiamo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Streams\n[![GoDoc](https://godoc.org/github.com/go-andiamo/streams?status.svg)](https://pkg.go.dev/github.com/go-andiamo/streams)\n[![Latest Version](https://img.shields.io/github/v/tag/go-andiamo/streams.svg?sort=semver\u0026style=flat\u0026label=version\u0026color=blue)](https://github.com/go-andiamo/streams/releases)\n[![codecov](https://codecov.io/gh/go-andiamo/streams/branch/main/graph/badge.svg?token=igjnZdgh0e)](https://codecov.io/gh/go-andiamo/streams)\n[![Go Report Card](https://goreportcard.com/badge/github.com/go-andiamo/streams)](https://goreportcard.com/report/github.com/go-andiamo/streams)\n\nA very light Streams implementation in Golang\n\n## Installation\nTo install Streams, use go get:\n\n    go get github.com/go-andiamo/streams\n\nTo update Streams to the latest version, run:\n\n    go get -u github.com/go-andiamo/streams\n\n## Interfaces\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eStream Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eAllMatch(p Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns whether all elements of this stream match the provided predicate\u003cbr\u003e\n                    \u003cem\u003eif the provided predicate is nil or the stream is empty, always returns false\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eAnyMatch(p Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns whether any elements of this stream match the provided predicate\u003cbr\u003e\n                    \u003cem\u003eif the provided predicate is nil or the stream is empty, always returns false\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eAppend(items ...T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream with all the elements of this stream followed by the specified elements\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eAsSlice()\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns the underlying slice\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e[]T\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eConcat(add Stream[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream with all the elements of this stream followed by all the elements of the added stream\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eCount(p Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns the count of elements that match the provided predicate\u003cbr\u003e\n                    \u003cem\u003eIf the predicate is nil, returns the count of all elements\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eint\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eDifference(other Stream[T], c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream that is the set difference between this and the supplied other stream\u003cbr\u003e\n                    \u003cem\u003eequality of elements is determined using the provided comparator (if the provided comparator is nil, the result is always empty)\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eDistinct()\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream of distinct elements in this stream\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eFilter(p Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream of elements in this stream that match the provided predicate\u003cbr\u003e\n                    \u003cem\u003eif the provided predicate is nil, all elements in this stream are returned\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eFirstMatch(p Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns an optional of the first element that matches the provided predicate\u003c\u003cbr\u003e\n                    if no elements match the provided predicate, an empty (not present) optional is returned\u003cbr\u003e\n                    \u003cem\u003eif the provided predicate is nil, the first element in this stream is returned\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e*Optional[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eForEach(c Consumer[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    performs an action on each element of this stream\u003cbr\u003e\n                    the action to be performed is defined by the provided consumer\u003cbr\u003e\n                    \u003cem\u003eif the provided consumer is nil, nothing is performed\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eerror\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eHas(v T, c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns whether this stream contains an element that is equal to the element value provided\u003cbr\u003e\n                    equality is determined using the provided comparator\u003cbr\u003e\n                    \u003cem\u003eif the provided comparator is nil, always returns false\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eIntersection(other Stream[T], c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream that is the set intersection of this and the supplied other stream\u003cbr\u003e\n                    \u003cem\u003eequality of elements is determined using the provided comparator (if the provided comparator is nil, the result is always empty)\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eIterator(ps ...Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns an iterator (pull) function\u003cbr\u003e\n                    the iterator function can be used in for loops, for example\u003cbr\u003e\n                    \u003cpre\u003e\nnext := strm.Iterator()\nfor v, ok := next(); ok; v, ok = next() {\n    fmt.Println(v)\n}\u003c/pre\u003e\n                    \u003ccode\u003eIterator\u003c/code\u003e can also optionally accept varargs of Predicate - which, if specified, are logically OR-ed on each pull to ensure that pulled elements match\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003efunc() (T, bool)\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eLastMatch(p Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns an optional of the last element that matches the provided predicate\u003cbr\u003e\n                    if no elements match the provided predicate, an empty (not present) optional is returned\u003cbr\u003e\n                    \u003cem\u003eif the provided predicate is nil, the last element in this stream is returned\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e*Optional[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eLen()\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns the length (number of elements) of this stream\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eint\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eLimit(maxSize int)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream whose number of elements is limited to the value provided\u003cbr\u003e\n                    if the maximum size is greater than the length of this stream, all elements are returned\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eMax(c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns the maximum element of this stream according to the provided comparator\u003cbr\u003e\n                    \u003cem\u003eif the provided comparator is nil or the stream is empty, an empty (not present) optional is returned\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e*Optional[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eMin(c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns the minimum element of this stream according to the provided comparator\u003cbr\u003e\n                    \u003cem\u003eif the provided comparator is nil or the stream is empty, an empty (not present) optional is returned\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e*Optional[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eMinMax(c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns the minimum and maximum element of this stream according to the provided comparator\u003cbr\u003e\n                    \u003cem\u003eif the provided comparator is nil or the stream is empty, an empty (not present) optional is returned for both\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e(*Optional[T], *Optional[T])\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eNoneMatch(p Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns whether none of the elements of this stream match the provided predicate\u003cbr\u003e\n                    \u003cem\u003eif the provided predicate is nil or the stream is empty, always returns true\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eNthMatch(p Predicate[T], nth int)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns an optional of the nth matching element (1 based) according to the provided predicate\u003cbr\u003e\n                    if the nth argument is negative, the nth is taken as relative to the last\u003cbr\u003e\n                    \u003cem\u003eif the provided predicate is nil, any element is taken as matching\u003c/em\u003e\n                    \u003cem\u003eif no elements match in the specified position, an empty (not present) optional is returned\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e*Optional[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eReverse()\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream composed of elements from this stream but in reverse order\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eSkip(n int)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream consisting of this stream after discarding the first \u003cem\u003e\u003cstrong\u003en\u003c/strong\u003e\u003c/em\u003e elements\u003cbr\u003e\n                    if the specified n to skip is equal to or greater than the number of elements in this stream, an empty stream is returned\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eSlice(start int, count int)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream composed of elements from this stream starting at the specified start and including the specified count (or to the end)\u003cbr\u003e\n                    the start is zero based (and less than zero is ignored)\u003cbr\u003e\n                    if the specified count is negative, items are selected from the start and then backwards by the count\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eSorted(c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream consisting of the elements of this stream, sorted according to the provided comparator\u003cbr\u003e\n                    \u003cem\u003eif the provided comparator is nil, the elements are not sorted\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eSymmetricDifference(other Stream[T], c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream that is the set symmetric difference between this and the supplied other stream\u003cbr\u003e\n                    \u003cem\u003eequality of elements is determined using the provided comparator (if the provided comparator is nil, the result is always empty)\u003c/em\u003e        \n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eUnion(other Stream[T], c Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream that is the set union of this and the supplied other stream\u003cbr\u003e\n                    \u003cem\u003eequality of elements is determined using the provided comparator (if the provided comparator is nil, the result is always empty)\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eUnique(c Comparator[T])\u003c/code\u003e\n                \u003cul\u003e\n                    creates a new stream of unique elements in this stream\u003cbr\u003e\n                    uniqueness is determined using the provided comparator\u003cbr\u003e\n                    if provided comparator is nil but the value type of elements in this stream are directly mappable (i.e. primitive or non-pointer types) then\n                    \u003ccode\u003eDistinct\u003c/code\u003e is used as the result, otherwise returns an empty stream\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eStream[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eOf[T any](values ...T) Stream[T]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream of the values provided\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eOfSlice[T any](s []T) Stream[T]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new stream around a slice\u003cbr\u003e\n                    \u003cem\u003eNote: Once created, If the slice changes the stream does not\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewStreamableSlice[T any](sl *[]T) Stream[T]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a Stream from a pointer to a slice\u003cbr\u003e\n                    \u003cem\u003eIt differs from casting a slice to Streamable in that if the underlying slice changes, so does the Stream\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003cstrong\u003eCasting as Streamable\u003c/strong\u003e\u003cbr\u003e\n                \u003cpre\u003e\nsl := []string{\"a\", \"b\", \"c\"}\ns := Streamable[string](sl)\u003c/pre\u003e\n                \u003cul\u003e\n                    casts a slice as a \u003ccode\u003eStream\u003c/code\u003e\u003cbr\u003e\n                    \u003cem\u003eNote: Once cast, if the slice changes the stream does not\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/table\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eComparator Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eCompare(v1, v2 T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    compares the two values lexicographically, i.e.:\n                    \u003cul\u003e\n                        \u003cli\u003ethe result should be \u003cstrong\u003e0\u003c/strong\u003e if v1 == v2\u003c/li\u003e\n                        \u003cli\u003ethe result should be \u003cstrong\u003e-1\u003c/strong\u003e if v1 \u003c v2\u003c/li\u003e\n                        \u003cli\u003ethe result should be \u003cstrong\u003e1\u003c/strong\u003e if v1 \u003e v2\u003c/li\u003e\n                    \u003c/ul\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eint\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eGreater(v1, v2 T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns true if v1 \u003e v2, otherwise false\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eGreaterOrEqual(v1, v2 T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns true if v1 \u003e= v2, otherwise false\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eEqual(v1, v2 T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns true if v1 == v2, otherwise false\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eLess(v1, v2 T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns true if v1 \u003c v2, otherwise false\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eLessOrEqual(v1, v2 T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns true if v1 \u003c= v2, otherwise false\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eNotEqual(v1, v2 T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    returns true if v1 != v2, otherwise false\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eReversed()\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new comparator that imposes the reverse ordering to this comparator\u003cbr\u003e\n                    the reversal is against less/greater as well as against equality/non-equality\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eComparator[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eThen(other Comparator[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new comparator from this comparator, with a following then comparator\n                    that is used when the initial comparison yields equal\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eComparator[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewComparator[T any](f ComparatorFunc[T]) Comparator[T]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new \u003ccode\u003eComparator\u003c/code\u003e from the function provided\u003cbr\u003e\n                    where the comparator function is:\u003cbr\u003e\n                    \u003ccode\u003etype ComparatorFunc[T any] func(v1, v2 T) int\u003c/code\u003e\u003cbr\u003e\n                    which returns:\n                    \u003cul\u003e\n                        \u003cli\u003e\u003cstrong\u003e0\u003c/strong\u003e if v1 == v2\u003c/li\u003e\n                        \u003cli\u003e\u003cstrong\u003e-1\u003c/strong\u003e if v1 \u003c v2\u003c/li\u003e\n                        \u003cli\u003e\u003cstrong\u003e1\u003c/strong\u003e if v1 \u003e v2\u003c/li\u003e\n                    \u003c/ul\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/table\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eConsumer Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eAccept(v T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    is called by the user of the consumer to supply a value\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eerror\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eAndThen(after Consumer[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new consumer from the current with a subsequent action to be performed\u003cbr\u003e\n                    \u003cem\u003emultiple consumers can be chained together as one using this method\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eConsumer[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewConsumer[T any](f ConsumerFunc[T]) Consumer[T]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new \u003ccode\u003eConsumer\u003c/code\u003e from the function provided\u003cbr\u003e\n                    where the consumer function is:\u003cbr\u003e\n                    \u003ccode\u003etype ConsumerFunc[T any] func(v T) error\u003c/code\u003e    \n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/table\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003ePredicate Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eTest(v T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    evaluates this predicate against the supplied value\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ebool\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eAnd(other Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a composed predicate that represents a short-circuiting logical AND of this predicate and another\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ePredicate[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eOr(other Predicate[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a composed predicate that represents a short-circuiting logical OR of this predicate and another\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ePredicate[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eNegate()\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a composed predicate that represents a logical NOT of this predicate\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003ePredicate[T]\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewPredicate[T any](f PredicateFunc[T]) Predicate[T]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new \u003ccode\u003ePredicate\u003c/code\u003e from the function provided\u003cbr\u003e\n                    where the predicate function is:\u003cbr\u003e\n                    \u003ccode\u003etype PredicateFunc[T any] func(v T) bool\u003c/code\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/table\u003e\n\u003c/details\u003e\n\n### Mapper Interfaces\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eMapper Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eMap(in Stream[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    converts the values in the input \u003ccode\u003eStream\u003c/code\u003e and produces a \u003ccode\u003eStream\u003c/code\u003e of output types\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e(Stream[R], error)\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewMapper[T any, R any](c Converter[T, R]) Mapper[T, R]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new \u003ccode\u003eMapper\u003c/code\u003e that will use the provided \u003ccode\u003eConverter\u003c/code\u003e\u003cbr\u003e\n                    \u003cem\u003e\u003ccode\u003eNewMapper\u003c/code\u003e panics if a nil \u003ccode\u003eConverter\u003c/code\u003e is supplied\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e        \n    \u003c/table\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eConverter Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eConvert(v T)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    converts a value of type \u003cstrong\u003eT\u003c/strong\u003e and returns a value of type \u003cstrong\u003eR\u003c/strong\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003e(R, error)\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewConverter[T any, R any](f ConverterFunc[T, R]) Converter[T, R]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new \u003ccode\u003eConverter\u003c/code\u003e from the function provided\u003cbr\u003e\n                    where the converter function is:\u003cbr\u003e\n                    \u003ccode\u003etype ConverterFunc[T any, R any] func(v T) (R, error)\u003c/code\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e        \n    \u003c/table\u003e\n\u003c/details\u003e\n\n### Reducer Interfaces\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eReducer Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eReduce(s Stream[T])\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    performs a reduction of the supplied \u003ccode\u003eStream\u003c/code\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eR\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewReducer[T any, R any](accumulator Accumulator[T, R]) Reducer[T, R]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new \u003ccode\u003eReducer\u003c/code\u003e that will use the supplied \u003ccode\u003eAccumulator\u003c/code\u003e\u003cbr\u003e\n                    \u003cem\u003e\u003ccode\u003eNewReducer\u003c/code\u003e panics if a nil \u003ccode\u003eAccumulator\u003c/code\u003e is supplied\u003c/em\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e        \n    \u003c/table\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eAccumulator Interface\u003c/strong\u003e\u003c/summary\u003e\n    \u003ctable\u003e\n        \u003ctr\u003e\n            \u003cth\u003eMethod and description\u003c/th\u003e\n            \u003cth\u003eReturns\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eApply(t T, r R)\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    adds the value of \u003cstrong\u003eT\u003c/strong\u003e to \u003cstrong\u003eR\u003c/strong\u003e, and returns the new \u003cstrong\u003eR\u003c/strong\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n            \u003ctd\u003e\n                \u003ccode\u003eR\u003c/code\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003cth colspan=\"2\"\u003eConstructors\u003c/th\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd colspan=\"2\"\u003e\n                \u003ccode\u003eNewAccumulator[T any, R any](f AccumulatorFunc[T, R]) Accumulator[T, R]\u003c/code\u003e\u003cbr\u003e\n                \u003cul\u003e\n                    creates a new \u003ccode\u003eAccumulator\u003c/code\u003e from the function provided\u003cbr\u003e\n                    where the accumulator function is:\u003cbr\u003e\n                    \u003ccode\u003etype AccumulatorFunc[T any, R any] func(t T, r R) R\u003c/code\u003e\n                \u003c/ul\u003e\n            \u003c/td\u003e\n        \u003c/tr\u003e        \n    \u003c/table\u003e\n\u003c/details\u003e\n\n## Examples\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eFind first match...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n    \"strings\"\n)\n\nfunc main() {\n    s := Of(\"a\", \"B\", \"c\", \"D\", \"e\", \"F\")\n    upperPredicate := NewPredicate(func(v string) bool {\n        return strings.ToUpper(v) == v\n    })\n    o := s.FirstMatch(upperPredicate)\n    o.IfPresentOtherwise(\n        func(v string) {\n            println(`Found: \"` + v + `\"`)\n        },\n        func() {\n            println(`Did not find an uppercase`)\n        },\n    )\n}\n```\n[try on go-playground](https://go.dev/play/p/C-GYuInfkNm)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eFind last match...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n    \"strings\"\n)\n\nfunc main() {\n    s := Of(\"a\", \"B\", \"c\", \"D\", \"e\", \"F\")\n    upperPredicate := NewPredicate(func(v string) bool {\n        return strings.ToUpper(v) == v\n    })\n    o := s.LastMatch(upperPredicate.Negate())\n    o.IfPresentOtherwise(\n        func(v string) {\n            println(`Found: \"` + v + `\"`)\n        },\n        func() {\n            println(`Did not find a lowercase`)\n        },\n    )\n}\n```\n[try on go-playground](https://go.dev/play/p/2UcwpZEuV-L)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eNth match...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    . \"github.com/go-andiamo/streams\"\n    \"strings\"\n)\n\nfunc main() {\n    s := Of(\"a\", \"B\", \"c\", \"D\", \"e\", \"F\", \"g\", \"H\", \"i\", \"J\")\n    upperPredicate := NewPredicate(func(v string) bool {\n        return strings.ToUpper(v) == v\n    })\n\n    for nth := -6; nth \u003c 7; nth++ {\n        s.NthMatch(upperPredicate, nth).IfPresentOtherwise(\n            func(v string) {\n                fmt.Printf(\"Found \\\"%s\\\" at nth pos %d\\n\", v, nth)\n            },\n            func() {\n                fmt.Printf(\"No match at nth pos %d\\n\", nth)\n            },\n        )\n    }\n}\n```\n[try on go-playground](https://go.dev/play/p/I_DrKK4ZXAT)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eSort descending \u0026 print...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    s := Of(\"311\", \"AAAA\", \"30\", \"3\", \"1\", \"Baaa\", \"4000\", \"0400\", \"40\", \"Aaaa\", \"BBBB\", \"4\", \"01\", \"2\", \"0101\", \"201\", \"20\")\n    _ = s.Sorted(StringComparator.Reversed()).ForEach(NewConsumer(func(v string) error {\n        println(v)\n        return nil\n    }))\n}\n```\n[try on go-playground](https://go.dev/play/p/bU6UZ479pF1)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eCompound sort...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    type myStruct struct {\n        value    int\n        priority int\n    }\n    myComparator := NewComparator(func(v1, v2 myStruct) int {\n        return IntComparator.Compare(v1.value, v2.value)\n    }).Then(NewComparator(func(v1, v2 myStruct) int {\n        return IntComparator.Compare(v1.priority, v2.priority)\n    }).Reversed())\n    s := Of(\n        myStruct{\n            value:    2,\n            priority: 2,\n        },\n        myStruct{\n            value:    2,\n            priority: 0,\n        },\n        myStruct{\n            value:    2,\n            priority: 1,\n        },\n        myStruct{\n            value:    1,\n            priority: 2,\n        },\n        myStruct{\n            value:    1,\n            priority: 1,\n        },\n        myStruct{\n            value:    1,\n            priority: 0,\n        },\n    )\n    _ = s.Sorted(myComparator).ForEach(NewConsumer(func(v myStruct) error {\n        fmt.Printf(\"Value: %d, Priority: %d\\n\", v.value, v.priority)\n        return nil\n    }))\n}\n```\n[try on go-playground](https://go.dev/play/p/TYeVcgjdAB3)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eMin and max...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    type myStruct struct {\n        value    int\n        priority int\n    }\n    myComparator := NewComparator(func(v1, v2 myStruct) int {\n        return IntComparator.Compare(v1.value, v2.value)\n    }).Then(NewComparator(func(v1, v2 myStruct) int {\n        return IntComparator.Compare(v1.priority, v2.priority)\n    }))\n    s := Of(\n        myStruct{\n            value:    2,\n            priority: 2,\n        },\n        myStruct{\n            value:    2,\n            priority: 0,\n        },\n        myStruct{\n            value:    2,\n            priority: 1,\n        },\n        myStruct{\n            value:    1,\n            priority: 2,\n        },\n        myStruct{\n            value:    1,\n            priority: 1,\n        },\n        myStruct{\n            value:    1,\n            priority: 0,\n        },\n    )\n    min := s.Min(myComparator)\n    min.IfPresentOtherwise(\n        func(v myStruct) {\n            fmt.Printf(\"Min... Value: %d, Priority: %d\\n\", v.value, v.priority)\n        },\n        func() {\n            println(\"No min found!\")\n        })\n    max := s.Max(myComparator)\n    max.IfPresentOtherwise(\n        func(v myStruct) {\n            fmt.Printf(\"Max... Value: %d, Priority: %d\\n\", v.value, v.priority)\n        },\n        func() {\n            println(\"No max found!\")\n        })\n}\n```\n[try on go-playground](https://go.dev/play/p/7uUKh5Qg-7L)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eSet intersection, union, difference and symmetric difference...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    s1 := Of(\"a\", \"B\", \"c\", \"C\", \"d\", \"D\", \"d\")\n    s2 := Of(\"e\", \"E\", \"a\", \"A\", \"b\")\n    println(\"Intersection...\")\n    _ = s1.Unique(StringInsensitiveComparator).Intersection(s2.Unique(StringInsensitiveComparator), StringInsensitiveComparator).\n        ForEach(NewConsumer(func(v string) error {\n            println(v)\n            return nil\n        }))\n    println(\"Union...\")\n    _ = s1.Unique(StringInsensitiveComparator).Union(s2.Unique(StringInsensitiveComparator), StringInsensitiveComparator).\n        ForEach(NewConsumer(func(v string) error {\n            println(v)\n            return nil\n        }))\n    println(\"Symmetric Difference...\")\n    _ = s1.Unique(StringInsensitiveComparator).SymmetricDifference(s2.Unique(StringInsensitiveComparator), StringInsensitiveComparator).\n        ForEach(NewConsumer(func(v string) error {\n            println(v)\n            return nil\n        }))\n    println(\"Difference (s1 to s2)...\")\n    _ = s1.Unique(StringInsensitiveComparator).Difference(s2.Unique(StringInsensitiveComparator), StringInsensitiveComparator).\n        ForEach(NewConsumer(func(v string) error {\n            println(v)\n            return nil\n        }))\n    println(\"Difference (s2 to s1)...\")\n    _ = s2.Unique(StringInsensitiveComparator).Difference(s1.Unique(StringInsensitiveComparator), StringInsensitiveComparator).\n        ForEach(NewConsumer(func(v string) error {\n            println(v)\n            return nil\n        }))\n}\n```\n[try on go-playground](https://go.dev/play/p/IMpym38xHXV)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eMap...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    type character struct {\n        name string\n        age  int\n    }\n    characters := OfSlice([]character{\n        {\n            `Frodo Baggins`,\n            50,\n        },\n        {\n            `Samwise Gamgee`,\n            38,\n        },\n        {\n            `Gandalf`,\n            2000,\n        },\n        {\n            `Aragorn`,\n            87,\n        },\n        {\n            `Legolas`,\n            200,\n        },\n        {\n            `Gimli`,\n            139,\n        },\n        {\n            `Meridoc Brandybuck`,\n            36,\n        },\n        {\n            `Peregrin Took`,\n            28,\n        },\n        {\n            `Boromir`,\n            40,\n        },\n    })\n\n    m := NewMapper(NewConverter[character, string](func(v character) (string, error) {\n        return v.name, nil\n    }))\n    names, _ := m.Map(characters)\n    _ = names.Sorted(StringComparator).ForEach(NewConsumer(func(v string) error {\n        println(v)\n        return nil\n    }))\n}\n```\n[try on go-playground](https://go.dev/play/p/oe5ZTSbzUyy)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eReduce...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    type account struct {\n        currency string\n        acNo     string\n        balance  float64\n    }\n    accounts := OfSlice([]account{\n        {\n            `GBP`,\n            `1051065`,\n            50.01,\n        },\n        {\n            `USD`,\n            `1931132`,\n            259.98,\n        },\n        {\n            `EUR`,\n            `1567807`,\n            313.25,\n        },\n        {\n            `EUR`,\n            `1009321`,\n            50.01,\n        },\n        {\n            `USD`,\n            `1573756`,\n            12.02,\n        },\n        {\n            `GBP`,\n            `1456044`,\n            99.99,\n        },\n    })\n\n    accum := NewAccumulator[account, map[string]float64](func(v account, r map[string]float64) map[string]float64 {\n        if r == nil {\n            r = map[string]float64{}\n        }\n        if cv, ok := r[v.currency]; ok {\n            r[v.currency] = cv + v.balance\n        } else {\n            r[v.currency] = v.balance\n        }\n        return r\n    })\n    r := NewReducer(accum)\n    for k, v := range r.Reduce(accounts) {\n        fmt.Printf(\"%s %f\\n\", k, v)\n    }\n}\n```\n[try on go-playground](https://go.dev/play/p/HwgwlkNFUTQ)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eFilter with composed predicate...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n    \"regexp\"\n    \"strings\"\n)\n\nfunc main() {\n    s := Of(\"aaa\", \"\", \"AAA\", \"012\", \"bBbB\", \"Ccc\", \"CCC\", \"D\", \"EeE\", \"eee\", \" \", \"  \", \"A12\")\n\n    pNotEmpty := NewPredicate(func(v string) bool {\n        return len(strings.Trim(v, \" \")) \u003e 0\n    })\n    rxNum := regexp.MustCompile(`^[0-9]+$`)\n    pNumeric := NewPredicate(func(v string) bool {\n        return rxNum.MatchString(v)\n    })\n    rxUpper := regexp.MustCompile(`^[A-Z]+$`)\n    pAllUpper := NewPredicate(func(v string) bool {\n        return rxUpper.MatchString(v)\n    })\n    rxLower := regexp.MustCompile(`^[a-z]+$`)\n    pAllLower := NewPredicate(func(v string) bool {\n        return rxLower.MatchString(v)\n    })\n    // only want strings that are non-empty and all numeric, all upper or all lower... \n    pFinal := pNotEmpty.And(pNumeric.Or(pAllUpper).Or(pAllLower))\n\n    _ = s.Filter(pFinal).ForEach(NewConsumer(func(v string) error {\n        println(v)\n        return nil\n    }))\n}\n```\n[try on go-playground](https://go.dev/play/p/WxOOpEv-kI0)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eDistinct vs Unique...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    s := Of(\"a\", \"A\", \"b\", \"B\", \"c\", \"C\")\n\n    println(\"Distinct...\")\n    _ = s.Distinct().ForEach(NewConsumer(func(v string) error {\n        println(v)\n        return nil\n    }))\n    println(\"Unique (case insensitive)...\")\n    _ = s.Unique(StringInsensitiveComparator).ForEach(NewConsumer(func(v string) error {\n        println(v)\n        return nil\n    }))\n}\n```\n[try on go-playground](https://go.dev/play/p/JZY9b6o6OLd)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eDistinct vs Unique (structs)...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    . \"github.com/go-andiamo/streams\"\n    \"strings\"\n)\n\ntype MyStruct struct {\n    value    string\n    priority int\n}\n\nfunc main() {\n    s1 := OfSlice([]MyStruct{\n        {\n            \"A\",\n            1,\n        },\n        {\n            \"A\",\n            2,\n        },\n        {\n            \"A\",\n            1,\n        },\n        {\n            \"A\",\n            2,\n        },\n    })\n\n    println(\"\\nStruct Distinct...\")\n    _ = s1.Distinct().ForEach(NewConsumer(func(v MyStruct) error {\n        fmt.Printf(\"Value: %s, Priority: %d\\n\", v.value, v.priority)\n        return nil\n    }))\n    println(\"\\nStruct Unique (no comparator)...\")\n    _ = s1.Unique(nil).ForEach(NewConsumer(func(v MyStruct) error {\n        fmt.Printf(\"Value: %s, Priority: %d\\n\", v.value, v.priority)\n        return nil\n    }))\n\n    s2 := OfSlice([]*MyStruct{\n        {\n            \"A\",\n            1,\n        },\n        {\n            \"A\",\n            2,\n        },\n        {\n            \"A\",\n            1,\n        },\n        {\n            \"A\",\n            2,\n        },\n    })\n\n    println(\"\\nStruct Ptr Distinct...\")\n    _ = s2.Distinct().ForEach(NewConsumer(func(v *MyStruct) error {\n        fmt.Printf(\"Value: %s, Priority: %d\\n\", v.value, v.priority)\n        return nil\n    }))\n    println(\"\\nStruct Ptr Unique (no comparator)...\")\n    _ = s2.Unique(nil).ForEach(NewConsumer(func(v *MyStruct) error {\n        fmt.Printf(\"Value: %s, Priority: %d\\n\", v.value, v.priority)\n        return nil\n    }))\n    cmp := NewComparator(func(v1, v2 *MyStruct) int {\n        return strings.Compare(v1.value, v2.value)\n    }).Then(NewComparator(func(v1, v2 *MyStruct) int {\n        return IntComparator.Compare(v1.priority, v2.priority)\n    }))\n    println(\"\\nStruct Ptr Unique (with comparator)...\")\n    _ = s2.Unique(cmp).ForEach(NewConsumer(func(v *MyStruct) error {\n        fmt.Printf(\"Value: %s, Priority: %d\\n\", v.value, v.priority)\n        return nil\n    }))\n}\n```\n[try on go-playground](https://go.dev/play/p/9Caw_RT4hwp)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eFor each...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n)\n\nvar stringValuePrinter = NewConsumer(func(v string) error {\n    println(v)\n    return nil\n})\n\nfunc main() {\n    s := Of(\"a\", \"b\", \"c\", \"d\")\n\n    _ = s.ForEach(stringValuePrinter)\n}\n```\n[try on go-playground](https://go.dev/play/p/yks2s2E8czr)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eIterator...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n)\n\nfunc main() {\n    s := Of(\"a\", \"b\", \"c\", \"d\")\n\n    next := s.Iterator()\n    for v, ok := next(); ok; v, ok = next() {\n        println(v)\n    }\n}\n```\n[try on go-playground](https://go.dev/play/p/Yae6ZLi2vVj)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e\u003cstrong\u003eIterator with predicate...\u003c/strong\u003e\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    . \"github.com/go-andiamo/streams\"\n    \"strings\"\n)\n\nfunc main() {\n    s := Of(\"a\", \"B\", \"c\", \"D\", \"e\", \"F\", \"g\", \"H\", \"i\", \"J\")\n    upper := NewPredicate(func(v string) bool {\n        return strings.ToUpper(v) == v\n    })\n\n    next := s.Iterator(upper)\n    for v, ok := next(); ok; v, ok = next() {\n        println(v)\n    }\n}\n```\n[try on go-playground](https://go.dev/play/p/GDQJDsZsSY9)\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-andiamo%2Fstreams","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-andiamo%2Fstreams","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-andiamo%2Fstreams/lists"}