Go Stream, like Java 8 Stream.
Blog Post: https://youthlin.com/?p=1755
go get github.com/youthlin/stream国内镜像: https://gitee.com/youthlin/stream
在 go.mod 中引入模块路径 github.com/youthlin/stream 及版本后,
再添加 replace 即可:
// go.mod require github.com/youthlin/stream latest replace github.com/youthlin/stream latest => gitee.com/youthlin/stream latesthttps://play.golang.org/p/nPQJYqA3-Jr
package main import ( "fmt" "github.com/youthlin/stream" "github.com/youthlin/stream/types" ) func main() { m := stream.IntRange(0, 10). Filter(func(e types.T) bool { return e.(int)%2 == 0 }). Map(func(e types.T) types.R { return e.(int) * 2 }). ReduceWith(map[int]string{}, func(acc types.R, e types.T) types.R { m := acc.(map[int]string) m[e.(int)] = fmt.Sprintf("<%d>", e) return m }) fmt.Println(m) // Output: // map[0:<0> 4:<4> 8:<8> 12:<12> 16:<16>] }type Stream interface { // stateless operate 无状态操作 Filter(types.Predicate) Stream // 过滤 Map(types.Function) Stream // 转换 FlatMap(func(t types.T) Stream) Stream // 打平 Peek(types.Consumer) Stream // peek 每个元素 // stateful operate 有状态操作 Distinct(types.IntFunction) Stream // 去重 Sorted(types.Comparator) Stream // 排序 Limit(int64) Stream // 限制个数 Skip(int64) Stream // 跳过个数 // terminal operate 终止操作 // 遍历 ForEach(types.Consumer) // return []T 转为切片 ToSlice() []types.T // return []X which X is the type of some ToElementSlice(some types.T) types.R // return []X which X is same as the `typ` representation ToSliceOf(typ reflect.Type) types.R // 测试是否所有元素满足条件 AllMatch(types.Predicate) bool // 测试是否没有元素满足条件 NoneMatch(types.Predicate) bool // 测试是否有任意元素满足条件 AnyMatch(types.Predicate) bool // Reduce return optional.Empty if no element. calculate result by (T, T) -> T from first element Reduce(accumulator types.BinaryOperator) optional.Optional // type of initValue is same as element. (T, T) -> T ReduceFrom(initValue types.T, accumulator types.BinaryOperator) types.T // type of initValue is different from element. (R, T) -> R ReduceWith(initValue types.R, accumulator func(types.R, types.T) types.R) types.R FindFirst() optional.Optional // 返回元素个数 Count() int64 } func ExampleOf() { fmt.Println(stream.Of().Count()) fmt.Println(stream.Of(1).Count()) fmt.Println(stream.Of("a", "b").Count()) var s = []int{1, 2, 3, 4} stream.Of(stream.Slice(s)...).ForEach(func(t types.T) { fmt.Printf("%d,", t) }) // Output: // 0 // 1 // 2 // 1,2,3,4, } func ExampleOfSlice() { var intArr = []int{1, 2, 3, 4} stream.OfSlice(intArr).ForEach(func(e types.T) { fmt.Printf("%d,", e) }) var nilArr []int stream.OfSlice(nilArr).ForEach(func(e types.T) { fmt.Printf("should not print") }) var strArr = []string{"a", "b"} stream.OfSlice(strArr). Map(func(e types.T) types.R { return fmt.Sprintf("<%s>", e) }). ForEach(func(e types.T) { fmt.Printf("%s,", e) }) // Output: // 1,2,3,4,<a>,<b>, } func ExampleOfMap() { var m1 = map[int]string{ 3: "c", 2: "b", 1: "a", } s := stream.OfMap(m1). Map(func(e types.T) types.R { p := e.(types.Pair) p.First, p.Second = p.Second, p.First return p }). Sorted(func(left types.T, right types.T) int { p1 := left.(types.Pair) p2 := right.(types.Pair) return p1.Second.(int) - p2.Second.(int) }). ToSlice() fmt.Println(s) stream.OfMap(nil).ForEach(func(e types.T) { fmt.Println("not print") }) // Output: // [{a 1} {b 2} {c 3}] } func ExampleStream_Filter() { stream.Of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9). Filter(func(e types.T) bool { return e.(int)%3 == 0 }). ForEach(func(e types.T) { fmt.Println(e) }) // Output: // 0 // 3 // 6 // 9 } func ExampleStream_Map() { stream.IntRange(0, 5). Map(func(t types.T) types.R { return fmt.Sprintf("<%d>", t.(int)) }). ForEach(func(t types.T) { fmt.Printf("%v", t) }) // Output: // <0><1><2><3><4> } func ExampleStream_FlatMap() { stream.Of([]int{0, 2, 4, 6, 8}, []int{1, 3, 5, 7, 9}). FlatMap(func(t types.T) stream.Stream { return stream.Of(stream.Slice(t)...) }). ForEach(func(t types.T) { fmt.Printf("%d", t) }) // Output: // 0246813579 } func ExampleStream_Sorted() { stream.IntRange(1, 10). Sorted(types.ReverseOrder(types.IntComparator)). ForEach(func(t types.T) { fmt.Printf("%d,", t) }) // Output: // 9,8,7,6,5,4,3,2,1, } func TestToMap(t *testing.T) { m := stream.IntRange(0, 10).ReduceWith(make(map[int]int), func(acc types.R, t types.T) types.R { acc.(map[int]int)[t.(int)] = t.(int) * 10 return acc }) t.Log(m) // Output: // map[0:0 1:10 2:20 3:30 4:40 5:50 6:60 7:70 8:80 9:90] }- v0.0.3 2020-12-08 add factory method: OfInts, OfInt64s, OfFloat32s, OfFloat64s, OfStrings;
add Stream method: ReduceBy - v0.0.2 2020-12-07 add factory method: OfSlice, OfMap
- v0.0.1 2020-11-12 first version
- add Benchmark test
- support parallel stream