Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

youthlin/stream

Open more actions menu

Repository files navigation

Go Stream

PkgGoDev Go Report Card Build Status codecov

Go Stream, like Java 8 Stream.

Blog Post: https://youthlin.com/?p=1755

How to get

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 latest

Play online

https://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>]
}

Examples

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]
}

Change Log

  • 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

Todo

  • add Benchmark test
  • support parallel stream

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.